bzoj 3261最大异或和
Description
给定一个非负整数序列{a},初始长度为N。
有M个操作,有以下两种操作类型:
1、Ax:添加操作,表示在序列末尾添加一个数x,序列的长度N+1。
2、Qlrx:询问操作,你需要找到一个位置p,满足l<=p<=r,使得:
a[p] xor a[p+1] xor ... xor a[N] xor x 最大,输出最大是多少。
Input
第一行包含两个整数 N ,M,含义如问题描述所示。
第二行包含 N个非负整数,表示初始的序列 A 。
接下来 M行,每行描述一个操作,格式如题面所述。
Output
假设询问操作有 T个,则输出应该有 T行,每行一个整数表示询问的答案。
题意:应该很清楚了;
题解:
①原题中的式子比较假: 化成max( (a[n] xor x)xor a[p-1] ) p∈[l,r];
②前面的now = (a[n] xor x)是一个定值,建立一颗字典树,从高位到低位考虑,一定是尽量选和now的那一位相反的数,对前缀建树,如果类似于普通01字典树,只是把一个数字插入经过的所有节点++,这个可持久的结构维护sum[r]-sum[l-1]第i位的节点值位0或1的个数;
③查询时,从高到低枚举位数j,如果和now的j位相反的数个数在sum[r]-sum[l-1]内存在,则进入这个节点,否则进入另一个节点执行同样操作,每次更新选择的数的j位;
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 using namespace std; 5 const int N=600010,S = 30; 6 int n,m,a[N],b[N],x,rt[N],sz,ch[N*S][2],sum[N*S]; 7 char gc(){ 8 static char *p1,*p2,s[1000000]; 9 if(p1==p2) p2=(p1=s)+fread(s,1,1000000,stdin); 10 return(p1==p2)?EOF:*p1++; 11 } 12 int rd(){ 13 int x = 0; char c = gc(); 14 while(c<'0'||c>'9') c = gc(); 15 while(c>='0'&&c<='9') x = x * 10 + c - '0',c = gc(); 16 return x; 17 } 18 bool opt(){ 19 char c = gc(); 20 while(c!='A'&&c!='Q') c = gc(); 21 return c=='A'; 22 } 23 int ins(int last,int val){ 24 int k,ret; k = ret = ++sz; 25 for(int i = 23;i >= 0;i--){ 26 sum[k] = sum[last] + 1; ch[k][0] = ch[last][0]; ch[k][1] = ch[last][1]; 27 int d = (val>>i)&1; 28 k = ch[k][d] = ++sz; last = ch[last][d]; 29 } 30 sum[k] = sum[last] + 1; 31 return ret; 32 } 33 int query(int k1,int k2,int val){ 34 int ret = 0; 35 for(int i = 23;i >= 0;i--){ 36 int d = (val>>i)&1; 37 if(sum[ch[k2][d^1]]-sum[ch[k1][d^1]]>0) 38 ret|=(1<<i),k1=ch[k1][d^1],k2=ch[k2][d^1]; 39 else k1=ch[k1][d],k2=ch[k2][d]; 40 } 41 return ret; 42 } 43 int main() 44 { freopen("bzoj3261.in","r",stdin); 45 freopen("bzoj3261.out","w",stdout); 46 n = rd()+1; m = rd(); 47 rt[1]=ins(rt[0],b[1]); 48 for(int i = 2;i <= n;i++) b[i] = b[i-1]^rd(),rt[i]=ins(rt[i-1],b[i]); 49 char s[10]; 50 for(int i = 1;i <= m;i++){ 51 if(opt()){ 52 n++; b[n]=b[n-1]^rd(); 53 rt[n]=ins(rt[n-1],b[n]); 54 } 55 else { 56 int l = rd(),r = rd(),x = rd(); 57 int tmp = query(rt[l-1],rt[r],b[n]^x); 58 printf("%d\n",tmp); 59 } 60 } 61 return 0; 62 }//by tkys_Austin;