Codeforces1665E MinimizOR 【可持久化trie】
分析:首先从左到右建出可持久化trie树,这样第r棵trie减去第l-1棵trie得到的结果对应的就是询问[l,r]的trie树。然后在trie树上游走,相当于从大到小讨论每一位。如果存在两个以上该位是0的数,则在trie树上向左走是没问题的;否则要么不存在该位是0的树,这时候只能在trie树上向右走;要么只存在一个该位为0的数,只需要把左边唯一对应的数插入到trie树的右边即可,再向右走就完美了。时间复杂度是O(nlog^2n)。
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 202000; 5 6 int a[maxn]; 7 8 struct node{ 9 int ch[2],cnt; 10 }nd[maxn*40]; 11 12 int root[maxn],num; 13 14 void init(){ 15 for(int i=1;i<=num;i++) nd[i].ch[0]=nd[i].ch[1]=nd[i].cnt=0; 16 for(int i=1;i<=num;i++) root[i] = 0; 17 num = 0; 18 } 19 void build(int i,int ce,int lst,int now){ 20 nd[now]=nd[lst]; 21 nd[now].cnt++; 22 if(ce == -1){ 23 return; 24 }else{ 25 if(a[i]&(1<<ce)){ 26 ++num; nd[now].ch[1] = num; 27 build(i,ce-1,nd[lst].ch[1],num); 28 }else{ 29 ++num; nd[now].ch[0] = num; 30 build(i,ce-1,nd[lst].ch[0],num); 31 } 32 } 33 } 34 35 void insert(int dt,int now,int lst,int ce){ 36 nd[now]=nd[lst]; 37 nd[now].cnt++; 38 if(ce == -1) return; 39 if(dt&(1<<ce)){ 40 ++num; nd[now].ch[1] = num; 41 insert(dt,num,nd[lst].ch[1],ce-1); 42 }else{ 43 ++num; nd[now].ch[0] = num; 44 insert(dt,num,nd[lst].ch[0],ce-1); 45 } 46 } 47 48 int query(int now,int lst,int ce){ 49 if(ce == -1) return 0; 50 int dt = nd[nd[now].ch[0]].cnt-nd[nd[lst].ch[0]].cnt; 51 if(dt >= 2){ 52 return query(nd[now].ch[0],nd[lst].ch[0],ce-1); 53 }else if(dt == 1){ 54 int dt = 0,nw = nd[now].ch[0],ns = nd[lst].ch[0],kd = ce-1; 55 while(kd >= 0){ 56 if(nd[nd[nw].ch[0]].cnt-nd[nd[ns].ch[0]].cnt){ 57 nw = nd[nw].ch[0],ns = nd[ns].ch[0]; 58 }else{ 59 nw = nd[nw].ch[1],ns = nd[ns].ch[1]; 60 dt += (1<<kd); 61 } 62 kd--; 63 } 64 int zx = ++num; 65 insert(dt,zx,nd[now].ch[1],ce-1); 66 int ans = (1<<ce)+query(zx,nd[lst].ch[1],ce-1); 67 num = zx-1; 68 return ans; 69 }else{ 70 return (1<<ce)+query(nd[now].ch[1],nd[lst].ch[1],ce-1); 71 } 72 } 73 74 int main(){ 75 ios::sync_with_stdio(false); 76 int t; cin >> t; 77 while(t--){ 78 init(); 79 int n; cin >> n; 80 for(int i=1;i<=n;i++) cin >> a[i]; 81 for(int i=1;i<=n;i++){ 82 root[i] = ++num; 83 build(i,29,root[i-1],root[i]); 84 } 85 int q; cin >> q; 86 for(int i=1;i<=q;i++){ 87 int l,r; cin >> l >> r; 88 cout << query(root[r],root[l-1],29)<<endl; 89 } 90 } 91 return 0; 92 }