二分+DP+Trie HDOJ 5715 XOR 遊戲

 

題目連接php

XOR 遊戲

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 256    Accepted Submission(s): 86
html

 

Problem Description
衆所周知,度度熊喜歡XOR運算[(XOR百科)](http://baike.baidu.com/view/674171.htm)。 c++

今天,它發明了一種XOR新遊戲,最開始,它有一個長度爲N的數組,度度熊能夠任意添加分割線,將數組劃分爲M段,且每段長度小於等於L。數組

固然這是個和XOR有關的遊戲,度度熊但願全部分組內異或和的最小值最大。spa

好比,長度爲4的數組{1,2,3,4},L爲3,能夠劃分爲{1|2,3,4} 或 {1,2|3,4} 或 {1,2,3|4},最小的異或值分別爲1,3,0,因此選第二種分割方法。htm

 

Input
第一行爲T,表示輸入數據組數。blog

對於每組數據,第一行包含三個整數N,M,L,第二行包含N個數,表示數組。遊戲

1≤T≤300ip

1≤N≤10000,1≤M≤10,1≤L≤N get

1≤Ai≤109

 

Output
對第i組數據,輸出 

Case #i:

而後輸出一行,僅包含一個整數,表示知足條件分組方法的最小異或值。

Sample Input
2
4 2 3
1 2 3 4
4 3 2
5 4 3 2

 

Sample Output
Case #1:
3
Case #2:
2

 

Source
2016"百度之星" - 複賽(Astar Round3)

 

題解:二分答案,dp[n][m]判斷n個數字分紅m段的可行性,那麼每一段的異或和不小於mid,先處理出前綴異或和,生成m棵trie樹,表示保存了dp[i][j]保存的最後的前綴異或和的位置.那麼轉移的話,就是知足max (A[j] ^ A[i] = (a[j+1] ^ a[j+2] ^ ... ^ a[i])) <= mid,求最大值就是trie裏搜異或和最大,首先要求j到i的距離小於L.

#include <bits/stdc++.h>

const int N = 1e4 + 5;
struct Trie {
    static const int NODE = N * 32;
    int ch[NODE][2], cnt[NODE];
    int sz;
    void init() {
        ch[0][0] = ch[0][1] = 0;
        sz = 1;
    }
    void insert(int x) {
        int u = 0;
        for (int c, i=29; i>=0; --i) {
            c = (x >> i) & 1;
            if (!ch[u][c]) {
                ch[sz][0] = ch[sz][1] = 0;
                cnt[sz] = 0;
                ch[u][c] = sz++;
            }
            u = ch[u][c];
            cnt[u]++;
        }
    }
    void _delete(int x) {
        int u = 0;
        for (int c, i=29; i>=0; --i) {
            c = (x >> i) & 1;
            int tu = u;
            u = ch[u][c];
            cnt[u]--;
            if (!cnt[u]) {
                ch[tu][c] = 0;
                return ;
            }
        }
    }
    int query(int x) {
        int ret = 0, u = 0;
        for (int c, i=29; i>=0; --i) {
            c = (x >> i) & 1;
            if (ch[u][c^1]) {
                ret += (1 << i);
                u = ch[u][c^1];
            } else {
                u = ch[u][c];
            }
        }
        return ret;
    }
}trie[11];
int a[N];
bool dp[N][11];
int n, m, k;

bool check(int val) {
    for (int i=0; i<=m; ++i) {
        trie[i].init ();
    }
    for (int i=0; i<=n; ++i) {
        for (int j=0; j<=m; ++j) {
            dp[i][j] = false;
        }
    }
    dp[0][0] = true;
    trie[0].insert (0);
    for (int i=1; i<=n; ++i) {
        for (int j=1; j<=m; ++j) {
            if (i > k && dp[i-k-1][j-1]) {
                trie[j-1]._delete (a[i-k-1]);
            }
            if (trie[j-1].query (a[i]) >= val) {
                dp[i][j] = true;
                trie[j].insert (a[i]);
            }
        }
    }
    return dp[n][m];
}

int solve() {
    scanf ("%d%d%d", &n, &m, &k);
    for (int i=1; i<=n; ++i) {
        scanf ("%d", a+i);
    }
    a[0] = 0;
    for (int i=1; i<=n; ++i) {
        a[i] = a[i-1] ^ a[i];
    }
    int left = 0, right = 1e9 + 7, ret = 0;
    while (left <= right) {
        int mid = left + right >> 1;
        if (check (mid)) {
            ret = mid;
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return ret;
}

int main() {
    int T;
    scanf ("%d", &T);
    for (int cas=1; cas<=T; ++cas) {
        printf ("Case #%d:\n%d\n", cas, solve ());
    }
    return 0;
}
相關文章
相關標籤/搜索