一个上午两道题,妥妥的作死。。。
首先还是按照之前思路建立可持久化trie,然后发现了点问题。。。
trie只能支持对于给定v求出最大xor值,也就是说我们要枚举a[i] (i ∈ [l, r]),于是单次询问复杂度O(n * 30),爆表
于是想到了需要预处理,方法是分块,预处理复杂度O(n * (n / sz) * 30),单次询问复杂度O(sz * 30)(sz为块的大小)
到这里的时候。。。网上的题解君们就只剩下程序了。。。于是害得蒟蒻理解错惹%>_<%
于是看到了BLADEVIL的题解,简直一目了然(但是程序注释不删不敢恭维= =)
重点要注意的就两个地方:
(1)f[i][j]为从第i个块的第一个元素开始,到第j个数的区间中,任意找两个数的xor值最大
(2)在计算l和r的时候。。。会爆int
1 /************************************************************** 2 Problem: 2741 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:5768 ms 7 Memory:11508 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <cmath> 12 #include <algorithm> 13 14 using namespace std; 15 typedef long long ll; 16 const int N = 12005; 17 const int sqrt_N = 120; 18 19 struct trie_node { 20 int son[2], cnt; 21 } t[N * 35]; 22 int cnt_trie = 1; 23 24 int n, m, a[N]; 25 int root[N], sz, w[N]; 26 int f[sqrt_N][N]; 27 28 inline int read() { 29 int x = 0; 30 char ch = getchar(); 31 while (ch < '0' || '9' < ch) 32 ch = getchar(); 33 while ('0' <= ch && ch <= '9') { 34 x = x * 10 + ch - '0'; 35 ch = getchar(); 36 } 37 return x; 38 } 39 40 int A[35]; 41 void insert(int &root, int v) { 42 int R = root, now = ++cnt_trie, i; 43 root = now; 44 for (i = 0; i <= 30; ++i) 45 A[i] = v & 1, v >>= 1; 46 reverse(A, A + 31); 47 for (i = 0; i <= 30; ++i) { 48 t[now].son[0] = t[R].son[0], t[now].son[1] = t[R].son[1]; 49 R = t[R].son[A[i]], now = t[now].son[A[i]] = ++cnt_trie; 50 t[now].cnt = t[R].cnt + 1; 51 } 52 } 53 54 int query(int x, int y, int v) { 55 int i, res = 0; 56 for (i = 0; i <= 30; ++i) 57 A[i] = v & 1, v >>= 1; 58 reverse(A, A + 31); 59 for (i = 0; i <= 30; ++i) { 60 if (t[t[y].son[!A[i]]].cnt - t[t[x].son[!A[i]]].cnt) 61 x = t[x].son[!A[i]], y = t[y].son[!A[i]], res += (1 << 30 - i); 62 else x = t[x].son[A[i]], y = t[y].son[A[i]]; 63 } 64 return res; 65 } 66 67 int Query(int l, int r) { 68 int i, maxi, res = w[l] < w[r] ? f[w[l] + 1][r] : 0; 69 for (i = min(w[l] * sz, r); i >= l; --i) 70 res = max(res, query(root[l - 1], root[r], a[i])); 71 return res; 72 } 73 74 void Block() { 75 int i, j, l; 76 sz = (int) sqrt(n); 77 for (i = 1; i <= n; ++i) { 78 w[i] = (int) (i - 1) / sz + 1; 79 for (j = 1; j <= w[i]; ++j) { 80 l = (j - 1) * sz; 81 f[j][i] = max(f[j][i - 1], query(root[l], root[i], a[i])); 82 } 83 } 84 } 85 86 int main() { 87 int i, x, y, l, r, last_ans = 0; 88 n = read(), m = read(); 89 for (i = 1, a[0] = root[0] = 0; i <= n; ++i) { 90 a[i] = a[i - 1] ^ read(), root[i] = root[i - 1]; 91 insert(root[i], a[i]); 92 } 93 Block(); 94 while (m--) { 95 x = read(), y = read(); 96 l = min(((ll) x + last_ans) % n + 1, ((ll) y + last_ans) % n + 1); 97 r = max(((ll) x + last_ans) % n + 1, ((ll) y + last_ans) % n + 1); 98 printf("%d\n", last_ans = Query(l - 1, r)); 99 } 100 return 0; 101 }
By Xs酱~ 转载请说明
博客地址:http://www.cnblogs.com/rausen