1. 程式人生 > >[BZOJ5338][TJOI2018]xor(可持久化Trie)

[BZOJ5338][TJOI2018]xor(可持久化Trie)

可持久化Trie模板題。

建兩種可持久化Trie,每個點兩棵,一棵對DFS求字首和,一棵對祖先求字首和。

或者樹剖,不好寫多少還多個log。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 4 #define For(i,x) for (int i=h[x],k; i; i=nxt[i])
 5 using namespace std;
 6 
 7 const int N=100010;
 8 int n,u,v,Q,x,y,z,op,nd,tim,cnt,t,a[N],rt1[N],rt2[N],fa[N][19
]; 9 int h[N],to[N<<1],nxt[N<<1],L[N],R[N],dep[N],ch[N*64][2],d[N*64]; 10 11 void add(int u,int v){ to[++cnt]=v; nxt[cnt]=h[u]; h[u]=cnt; } 12 13 void ins(int &x,int y,int k){ 14 int tmp=++nd; x=tmp; 15 for (int i=30; ~i; i--){ 16 ch[x][0]=ch[y][0]; ch[x][1]=ch[y][1
]; d[x]=d[y]+1; 17 int t=(k>>i)&1; ch[x][t]=++nd; x=ch[x][t]; y=ch[y][t]; 18 } 19 d[x]=d[y]+1; x=tmp; 20 } 21 22 int cal1(int x,int y,int k){ 23 int res=0; 24 for (int i=30; ~i; i--){ 25 int t=((k>>i)&1)^1; 26 if (d[ch[y][t]]-d[ch[x][t]]) res^=1
<<i,x=ch[x][t],y=ch[y][t]; 27 else x=ch[x][t^1],y=ch[y][t^1]; 28 } 29 return res; 30 } 31 32 int cal2(int s1,int s2,int s3,int s4,int k){ 33 int res=0; 34 for (int i=30; ~i; i--){ 35 int t=((k>>i)&1)^1; 36 if (d[ch[s1][t]]+d[ch[s2][t]]-d[ch[s3][t]]-d[ch[s4][t]]) 37 res^=1<<i,s1=ch[s1][t],s2=ch[s2][t],s3=ch[s3][t],s4=ch[s4][t]; 38 else s1=ch[s1][t^1],s2=ch[s2][t^1],s3=ch[s3][t^1],s4=ch[s4][t^1]; 39 } 40 return res; 41 } 42 43 int Lca(int u,int v){ 44 if (dep[u]<dep[v]) swap(u,v); 45 int t=dep[u]-dep[v]; 46 for (int i=17; ~i; i--) if (t&(1<<i)) u=fa[u][i]; 47 if (u==v) return u; 48 for (int i=17; ~i; i--) if (fa[u][i]!=fa[v][i]) u=fa[u][i],v=fa[v][i]; 49 return fa[u][0]; 50 } 51 52 void dfs(int x){ 53 rep(i,1,17) fa[x][i]=fa[fa[x][i-1]][i-1]; 54 L[x]=++tim; ins(rt1[tim],rt1[tim-1],a[x]); 55 For(i,x) if ((k=to[i])!=fa[x][0]) 56 fa[k][0]=x,ins(rt2[k],rt2[x],a[k]),dep[k]=dep[x]+1,dfs(k); 57 R[x]=tim; 58 } 59 60 int main(){ 61 freopen("bzoj5338.in","r",stdin); 62 freopen("bzoj5338.out","w",stdout); 63 scanf("%d%d",&n,&Q); 64 rep(i,1,n) scanf("%d",&a[i]); 65 rep(i,2,n) scanf("%d%d",&u,&v),add(u,v),add(v,u); 66 dfs(1); 67 while (Q--){ 68 scanf("%d%d%d",&op,&x,&y); 69 if (op==1) printf("%d\n",cal1(rt1[L[x]-1],rt1[R[x]],y)); 70 else scanf("%d",&z),t=Lca(x,y),printf("%d\n",cal2(rt2[x],rt2[y],rt2[t],rt2[fa[t][0]],z)); 71 } 72 return 0; 73 }