这个对数字建二进制trie,然后启发式合并,最重要的是Push_up()操作和Merge()操作,解决了复杂度的问题。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 const int N=100010,M=2000010; 6 int cnt,fir[N],to[N*2],nxt[N*2]; 7 void addedge(int a,int b){ 8 nxt[++cnt]=fir[a]; 9 to[fir[a]=cnt]=b; 10 } 11 int T,n,Q,cas,tot,dp[N],rt[N]; 12 int ch[M][2],sum[M],p[M],w[M],val[M]; 13 14 int Query(int x,int k,int d){ 15 if(d==-1)return val[x];int c=(k>>d)&1; 16 if(ch[x][c])return Query(ch[x][c],k,d-1); 17 else return Query(ch[x][c^1],k,d-1); 18 } 19 20 void Push_up(int x,int d){ 21 int l=ch[x][0],r=ch[x][1]; 22 sum[x]=sum[l]+sum[r]; 23 if(!sum[l]||!sum[r]) 24 p[x]=sum[l]?p[l]:p[r]; 25 else if(sum[l]>1&&sum[r]>1) 26 p[x]=p[l]>p[r]?p[l]:p[r]; 27 else if(sum[l]==1&&sum[r]==1) 28 p[x]=p[l]^p[r]; 29 else{ 30 if(sum[l]!=1)swap(l,r); 31 p[x]=p[l]^Query(r,p[l],d-1); 32 } 33 } 34 35 void Insert(int &x,int k,int d){ 36 if(!x)x=++tot; 37 if(d==-1){ 38 if(sum[x])p[x]=0; 39 else p[x]=val[x]=k; 40 sum[x]+=1;return; 41 } 42 if((k>>d)&1)Insert(ch[x][1],k,d-1); 43 else Insert(ch[x][0],k,d-1); 44 Push_up(x,d); 45 } 46 47 int Merge(int x,int y,int d){ 48 if(!x||!y)return x|y; 49 if(d==-1){ 50 sum[x]+=sum[y]; 51 if(sum[x]>1)p[x]=0; 52 else p[x]=val[x]; 53 return x; 54 } 55 ch[x][0]=Merge(ch[x][0],ch[y][0],d-1); 56 ch[x][1]=Merge(ch[x][1],ch[y][1],d-1); 57 Push_up(x,d);return x; 58 } 59 60 void DFS(int x,int fa){ 61 Insert(rt[x],w[x],16); 62 for(int i=fir[x];i;i=nxt[i]) 63 if(to[i]!=fa){DFS(to[i],x); 64 rt[x]=Merge(rt[x],rt[to[i]],16); 65 } 66 if(sum[rt[x]]>=2)dp[x]=p[rt[x]]; 67 } 68 69 void Initialization(){ 70 memset(fir,0,sizeof(fir)); 71 memset(sum,0,sizeof(sum)); 72 memset(dp,-1,sizeof(dp)); 73 memset(rt,0,sizeof(rt)); 74 memset(ch,0,sizeof(ch)); 75 cnt=tot=0; 76 } 77 int main(){ 78 scanf("%d",&T); 79 while(T--){ 80 scanf("%d",&n); 81 Initialization(); 82 for(int i=1;i<=n;i++) 83 scanf("%d",&w[i]); 84 for(int i=1,a,b;i<n;i++){ 85 scanf("%d%d",&a,&b); 86 addedge(a,b);addedge(b,a); 87 } 88 DFS(1,0); 89 scanf("%d",&Q); 90 printf("Case #%d:\n",++cas); 91 while(Q--){ 92 int x;scanf("%d",&x); 93 printf("%d\n",dp[x]); 94 } 95 } 96 return 0; 97 }