寫過可持久化線段樹,可是歷來沒寫過可持久化的Trie,今天補一補。node
題目就是典型的給你一個數x,和一個數集,問x和裏面的某個數xor起來的最大值是多少。ios
最原始的是數集是固定的,只須要對數集按照高到低位去建Trie,而後貪心匹配就能夠了。ui
這裏則是對樹上路徑的操做,其實也是同樣的,對每一個節點x維護root到x的Trie,而後紀錄下往左走往右走的葉子節點個數,設z=lca(x,y),那麼到了個某個節點可否往某個兒子走的限制條件是 sz[ch[x][c]]+sz[ch[y][c]]-2*sz[ch[z][c]]>0,這樣說明下面是存在c的兒子的,接着往下走便可。固然這樣算實際上是會漏掉lca的,因此最後還要和lca取最大值。spa
區間的詢問做爲這題的特例同理也是能夠處理的。blog
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <algorithm> #include <cmath> #include <queue> #include <cassert> #include <vector> #include <set> using namespace std; #define maxn 120000 #define maxnode 2200000 #define maxlogv 16 vector<int> G[maxn]; int n,m; int a[maxn]; int f[maxlogv+2][maxn]; int dep[maxn]; int ch[maxnode][2]; int sz[maxnode]; int tot; int root[maxn]; int newnode(){ memset(ch[tot],0,sizeof(ch[tot])); sz[tot]=0; return tot++; } // insert val for x with father as y void insert(int x,int y,int val) { x=root[x];y=root[y]; for(int i=15;i>=0;--i){ int c=(val>>i)&1; if(!ch[x][c]){ int id=newnode(); ch[x][c]=id; ch[x][!c]=ch[y][!c]; sz[ch[x][c]]=sz[ch[y][c]]; } x=ch[x][c],y=ch[y][c]; ++sz[x]; } } void dfs(int u,int fa) { f[0][u]=fa;dep[u]=dep[fa]+1; root[u]=newnode(); insert(u,fa,a[u]); for(int i=0;i<G[u].size();++i){ int v=G[u][i]; if(v==fa) continue; dfs(v,u); } } int lca(int u,int v) { if(dep[u]>dep[v]) swap(u,v); for(int k=0;k<maxlogv;++k){ if( (dep[v]-dep[u])>>k&1){ v=f[k][v]; } } if(u==v) return u; for(int k=maxlogv-1;k>=0;--k){ if(f[k][u]!=f[k][v]){ u=f[k][u]; v=f[k][v]; } } return f[0][u]; } int query(int x,int y,int val) { int z=lca(x,y);int res=a[z]^val; x=root[x],y=root[y],z=root[z]; int ret=0; for(int i=15;i>=0;--i){ int c=(val>>i)&1; if(sz[ch[x][!c]]+sz[ch[y][!c]]-2*sz[ch[z][!c]]>0){ ret+=1<<i; c=!c; } x=ch[x][c]; y=ch[y][c]; z=ch[z][c]; } return max(ret,res); } int main() { while(cin>>n>>m){ for(int i=1;i<=n;++i){ scanf("%d",a+i); G[i].clear(); } int ui,vi; for(int i=0;i<n-1;++i){ scanf("%d%d",&ui,&vi); G[ui].push_back(vi); G[vi].push_back(ui); } memset(root,0,sizeof(root)); tot=1; memset(f,0,sizeof(f)); memset(sz,0,sizeof(sz)); dep[0]=0; dfs(1,0); for(int k=0;k+1<maxlogv;++k){ for(int v=1;v<=n;++v){ if(f[k][v]==0) f[k+1][v]=0; else f[k+1][v]=f[k][f[k][v]]; } } int xi,yi,zi; for(int i=0;i<m;++i){ scanf("%d%d%d",&xi,&yi,&zi); printf("%d\n",query(xi,yi,zi)); } } return 0; }