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 }

 

posted @ 2022-04-09 10:36  menhera  阅读(118)  评论(0编辑  收藏  举报