题:http://acm.hdu.edu.cn/showproblem.php?pid=4757
题意:给一棵树,每个节点有权值。每次询问要求回答一个值XOR某条路径上的一个点的最大值。
分析:我们在学可持续化01字典树时,写的模板题是支持区间查询的,插入一个数是pre是和u-1之间建立,那么在树上这个关系就是父亲与儿子的关系建立可持续化01字典树;
然后查询久查询[fa[lca[x,y]],x]和[fa[lca[x,y]],y]这俩个区间;
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<vector> using namespace std; const int M=1e5+5; #define pb push_back struct TRIE{ int trie[M*32][2],sum[M*32],val[M*32]; int rt[M*32],tot; void init(){ tot=0; memset(trie,0,sizeof(trie)); memset(sum,0,sizeof(sum)); memset(val,0,sizeof(val)); memset(rt,0,sizeof(rt)); rt[0]=++tot; } void Insert(int pre,int now,int x){ for(int i=18;i>=0;i--){ int id=(x>>i)&1; trie[now][id]=++tot; trie[now][id^1]=trie[pre][id^1]; now=trie[now][id]; pre=trie[pre][id]; sum[now]=sum[pre]+1; } val[now]=x; } int query(int l,int r,int x){ for(int i=18;i>=0;i--){ int id=(x>>i)&1; if(sum[trie[r][id^1]]-sum[trie[l][id^1]]>0) r=trie[r][id^1],l=trie[l][id^1]; else r=trie[r][id],l=trie[l][id]; } return val[r]^x; } }Trie; int p[M],grand[M][20],s,n,m,root,deep[M]; vector<int>g[M]; void dfs(int u,int fa){ Trie.rt[u]=++Trie.tot; Trie.Insert(Trie.rt[fa],Trie.rt[u],p[u]); deep[u]=deep[fa]+1; grand[u][0]=fa; for(int i=1;i<=s;i++){ grand[u][i]=grand[grand[u][i-1]][i-1]; if(!grand[u][i]) break; } for(auto v:g[u]){ if(v!=fa) dfs(v,u); } } void init(){ s=floor(log(1.0*n)/log(2.0)); deep[0]=0; dfs(root,0); } int LCA(int u,int v){ int a=u,b=v; if(deep[a]>deep[b]) swap(a,b) ; for(int i=s;i>=0;i--){ if(deep[b]>deep[a]&&deep[a]<=deep[grand[b][i]]) b=grand[b][i]; } for(int i=s;i>=0;i--){ if(grand[b][i]!=grand[a][i]) a=grand[a][i],b=grand[b][i]; } if(a!=b) a=grand[a][0],b=grand[b][0]; return a; } int main(){ while(scanf("%d%d",&n,&m)!=EOF){ Trie.init(); for(int i=0;i<=n;i++) g[i].clear(); memset(grand,0,sizeof(grand)); for(int i=1;i<=n;i++) scanf("%d",&p[i]); for(int u,v,i=1;i<n;i++){ scanf("%d%d",&u,&v); g[u].pb(v); g[v].pb(u); } root=1; init(); while(m--){ int u,v,x; scanf("%d%d%d",&u,&v,&x); int lca=LCA(u,v); int fa=grand[lca][0]; printf("%d ",max(Trie.query(Trie.rt[fa],Trie.rt[u],x),Trie.query(Trie.rt[fa],Trie.rt[v],x))); } } return 0; }