BZOJ5338 [TJOI2018] Xor 【可持久化Trie树】【dfs序】

题目分析:

  很无聊的一道题目。首先区间内单点对应异或值的询问容易想到trie树。由于题目在树上进行,case1将路径分成两段,然后dfs的时候顺便可持久化trie树做询问。case2维护dfs序,对dfs序建可持久化的trie树。这样做的空间复杂度是O(nw),时间复杂度是O(nw).

代码:

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 
  4 const int maxn=102000;
  5 
  6 int n,q;
  7 int v[maxn];
  8 vector<int> g[maxn];
  9 
 10 vector<pair<int,int> > qy[maxn];
 11 vector<pair<int,int> > vec;
 12 
 13 int ans[maxn],num,kd[maxn];
 14 int dep[maxn],dfsin[maxn],dfsout[maxn],fa[maxn];
 15 
 16 vector<pair<int,int> > Lca[maxn];
 17 int pre[maxn];
 18 
 19 int found(int x){
 20     int rx = x; while(pre[rx] != rx) rx = pre[rx];
 21     while(pre[x] != rx){
 22     int t = pre[x]; pre[x] = rx; x = t;
 23     }
 24     return rx;
 25 }
 26 
 27 void dfs(int now,int dp,int f){
 28     dfsin[now] = dfsout[now] = ++num;fa[now] = f; dep[now] = dp;
 29     for(auto pr:Lca[now]){
 30     if(dep[pr.first] == 0) continue;
 31     int la = found(pr.first);
 32     qy[now].push_back(make_pair(la,pr.second));
 33     qy[pr.first].push_back(make_pair(la,pr.second));
 34     }
 35     for(auto i:g[now]){
 36     if(i == f) continue;
 37     dfs(i,dp+1,now);
 38     dfsout[now] = dfsout[i];
 39     }
 40     pre[found(now)] = found(f);
 41 }
 42 
 43 void read(){
 44     scanf("%d%d",&n,&q);
 45     for(int i=1;i<=n;i++) scanf("%d",&v[i]);
 46     for(int i=1;i<n;i++){
 47     int x,y; scanf("%d%d",&x,&y);
 48     g[x].push_back(y); g[y].push_back(x);
 49     }
 50     for(int i=1;i<=q;i++){
 51     int cas; scanf("%d",&cas);
 52     if(cas == 1){
 53         int x,y; scanf("%d%d",&x,&y);
 54         vec.push_back(make_pair(x,i));kd[i] = y;
 55     }else{
 56         int x,y,z; scanf("%d%d%d",&x,&y,&z);
 57         Lca[x].push_back(make_pair(y,i));
 58         if(x!=y) Lca[y].push_back(make_pair(x,i));
 59         kd[i] = z;
 60     }
 61     }
 62     for(int i=1;i<=n;i++) pre[i] = i;
 63     dfs(1,1,0);
 64 }
 65 
 66 int his[maxn],om;
 67 int sz[maxn*130],ch[maxn*130][2];
 68 
 69 void follow(int pt,int last,int dt){
 70     int hbit = 30;
 71     while(hbit!=-1){
 72     if((1<<hbit)&dt){
 73         ch[pt][0] = ch[last][0];
 74         ch[pt][1] = ++num;
 75         pt = num; last = ch[last][1];
 76         sz[pt] = sz[last]+1;
 77     }else{
 78         ch[pt][1] = ch[last][1];
 79         ch[pt][0] = ++num;
 80         pt = num; last = ch[last][0];
 81         sz[pt] = sz[last]+1;
 82     }
 83     hbit--;
 84     }
 85 }
 86 
 87 void ins(int now){
 88     int last = his[om-1];
 89     num++;int pt = num; sz[pt] = sz[last]+1;
 90     his[om] = num;
 91     follow(pt,last,v[now]);
 92 }
 93 
 94 int query(int now,int last,int z){
 95     now = his[now]; last = his[last];
 96     int hbit = 30;
 97     while(hbit!=-1){
 98     if((1<<hbit)&z){
 99         if(sz[ch[now][0]]-sz[ch[last][0]]){
100         now = ch[now][0];last = ch[last][0];
101         }else{
102         z -= (1<<hbit);now = ch[now][1];last = ch[last][1];
103         }
104     }else{
105         if(sz[ch[now][1]]-sz[ch[last][1]]){
106         z += (1<<hbit);
107         now = ch[now][1];last = ch[last][1];
108         }else{
109         now = ch[now][0];last = ch[last][0];
110         }
111     }
112     hbit--;
113     }
114     return z;
115 }
116 
117 void del(int now){his[om] = 0;}
118 
119 void dfs2(int now){
120     om++;ins(now);
121     for(auto pr:qy[now]){
122     int last = dep[pr.first]-1,data = kd[pr.second];
123     ans[pr.second] = max(ans[pr.second],query(dep[now],last,data));
124     }
125     for(auto i:g[now]){
126     if(i == fa[now]) continue;
127     dfs2(i); 
128     }
129     del(now);om--;
130 }
131 
132 void dfs3(int now){
133     om++;ins(now);
134     for(auto i:g[now]){
135     if(i == fa[now]) continue;
136     dfs3(i);
137     }
138 }
139 
140 void work(){
141     num = 1;his[0] = 1;
142     dfs2(1);
143     memset(ch,0,sizeof(ch));memset(sz,0,sizeof(sz));
144     num = 1;his[0] = 1;om = 0;
145     dfs3(1);
146     for(auto pr:vec){
147     int st = dfsin[pr.first],ed = dfsout[pr.first];
148     ans[pr.second] = query(ed,st-1,kd[pr.second]);
149     }
150     for(int i=1;i<=q;i++) printf("%d\n",ans[i]);
151 }
152 
153 int main(){
154     read();
155     work();
156     return 0;
157 }

 

posted @ 2018-05-19 11:41  menhera  阅读(338)  评论(0编辑  收藏  举报