【bzoj3261】最大异或和
题目描述:
给定一个非负整数序列 {a},初始长度为 N。
有 M个操作,有以下两种操作类型:
1 、A x:添加操作,表示在序列末尾添加一个数 x,序列的长度 N+1。
2 、Q l r x:询问操作,你需要找到一个位置 p,满足 l<=p<=r,使得:
a[p] xor a[p+1] xor ... xor a[N] xor x 最大,输出最大是多少
样例输入:
5 5
2 6 4 3 6
A 1
Q 3 5 4
A 4
Q 5 7 0
Q 3 6 6
样例输出:
4
5
6
题解:
可持久化Trie树,在只有二叉的时候和可持久化线段树非常像。把每个前缀异或和二进制转化后插入可持久化Trie树中,然后询问只要和b[n]^x比较,如果有不同的位就走到不同的位里面去。
代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #ifdef WIN32 #define LL "%I64d" #else #define LL "%lld" #endif #ifdef CT #define debug(...) printf(__VA_ARGS__) #define setfile() #else #define debug(...) #define filename "" #define setfile() freopen(filename".in","r",stdin);freopen(filename".out","w",stdout); #endif #define R register #define getc() (S==T&&(T=(S=B)+fread(B,1,1<<15,stdin),S==T)?EOF:*S++) #define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b)) #define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b)) #define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0) #define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0) char B[1<<15],*S=B,*T=B; inline int FastIn() { R char ch;R int cnt=0;R bool minus=0; while (ch=getc(),(ch < '0' || ch > '9') && ch != '-'); ch == '-' ?minus=1:cnt=ch-'0'; while (ch=getc(),ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0'; return minus?-cnt:cnt; } #define maxn 700010 #define maxt 15000010 int trie[maxt][2], b[maxn], sum[maxt], root[maxn], cnt ,p[30]; inline void Insert (R int last, R int x) { R int ch = last; for (R int i = 24; i>=0 ; i--) { R int t = x&p[i]; t >>= i; sum[++cnt] = sum[ch] + 1; trie[cnt][t] = cnt + 1; trie[cnt][t ^ 1] = trie[ch][t ^ 1]; ch = trie[ch][t] ; } sum[++cnt] = sum[ch] + 1; } inline int Query (R int l, R int r, R int x) { R int ans = 0; for (R int i = 24; i>=0 ; i--) { R int t = x&p[i]; t >>= i; if (sum[trie[r][t^1]] - sum[trie[l][t^1]] > 0) { ans |= p[i]; r = trie[r][t^1]; l = trie[l][t^1]; } else { r = trie[r][t]; l = trie[l][t]; } } return ans; } int main() { //setfile(); R int n = FastIn(), m = FastIn(); p[0] = 1; for (R int i = 1; i <= 24; i++) p[i] = p[i - 1] << 1; b[1] = 0 ; root[1] = 1 ; Insert(0 , 0); n++; for (R int i = 2; i <= n; i++) { R int a = FastIn(); b[i] = b[i - 1] ^ a; root[i] = cnt + 1; Insert(root[i - 1], b[i]); } for (R int i = 1; i <= m; i++) { R char cmd = getc(); while (cmd!='A'&&cmd!='Q') cmd = getc(); if (cmd=='A') { R int x = FastIn(); ++n; b[n] = b[n - 1] ^ x; root[n] = cnt + 1; Insert(root[n - 1], b[n]); } else { R int l = FastIn(), r = FastIn(), x = FastIn(); //printf("%d %d %d\n",l , r ,x ); printf("%d\n",Query(root[l - 1], root[r], b[n] ^ x) ); } } return 0; }