【xsy1147】 异或(xor) 可持久化trie

我的脑回路可能比较奇怪。

我们对这些询问离线,将所得序列${a}$的后缀和建$n$棵可持久化$trie$。

对于一组询问$(l,r,x)$,我们在主席树上询问第$l$棵树$-$第r$+1$棵树中与$suma[n']\ xor\ x$异或的最大值即可。

这个时间复杂度是$O(n\ log\ a)$的。

 1 #include<bits/stdc++.h>
 2 #define M 600005
 3 using namespace std;
 4 
 5 struct trie{int a[2],sum=0;}a[M*30];
 6 int root[M]={0},use=0;
 7 void updata(int &x,int dep,int Val){
 8     bool k=Val&(1<<dep);
 9     a[++use]=a[x]; a[x=use].sum++;
10     if(dep==-1) return;
11     updata(a[x].a[k],dep-1,Val);
12 }
13 int query(int x,int y,int Val){
14     int res=0;
15     for(int i=29;~i;i--){
16         bool k=Val&(1<<i); k^=1;
17         int cnt=a[a[x].a[k]].sum-a[a[y].a[k]].sum;
18         if(cnt) res|=1<<i,x=a[x].a[k],y=a[y].a[k];
19         else x=a[x].a[k^1],y=a[y].a[k^1];
20     }
21     return res;
22 }
23 
24 int val[M]={0};
25 int n,m;
26 int nown[M]={0},l[M]={0},r[M]={0},X[M]={0},cnt=0;
27 int main(){
28     scanf("%d%d",&n,&m);
29     for(int i=1;i<=n;i++) scanf("%d",val+i);
30     while(m--){
31         char op[10]; scanf("%s",op);
32         if(op[0]=='A') {scanf("%d",val+(++n)); continue;}
33         nown[++cnt]=n; 
34         scanf("%d%d%d",l+cnt,r+cnt,X+cnt);
35     }
36     for(int i=n;i;i--){
37         val[i]^=val[i+1]; root[i]=root[i+1];
38         updata(root[i],29,val[i]);
39     }
40     for(int i=1;i<=cnt;i++){
41         printf("%d\n",query(root[l[i]],root[r[i]+1],val[nown[i]+1]^X[i]));
42     }
43 }

猜你喜欢

转载自www.cnblogs.com/xiefengze1/p/9831288.html