【xsy1122】 路径 点分治+trie
题目大意:给你一棵n个点的树,树边上有边权,对于每一个点,你要求出经过该点的所有的路径中,路径异或和最大的值。
数据范围:$n≤10^5$,边权$≤10^9$。
我们考虑枚举每一条路径,显然这个是会T的,于是我们用点分治来实现这个过程。
对于一棵以$x$为根的子树,假设它有$k$个儿子,编号$v1....k$。
我们维护一棵$trie$树,记录所有从根到以$v1,v2.....vp$为跟的子树中的路径长度。
对于从跟到第$p+1$个儿子为跟的树中的每一条路径,我们都丢到$trie$树中查询与最大的异或值。
在查询最大值的过程中,我们维护一个$max_i$,表示从根到i的路径上的最大路径异或和。我们可以通过简单的标记上传去实现更新。
然后再将所有终点在$p+1$个子树中的路径加入到$trie$树种。
时间复杂度:$O(n\ log\ n\ log\ v)$。
1 #include<bits/stdc++.h> 2 #define M 100005 3 #define INF ((1<<31)-1) 4 using namespace std; 5 6 struct edge{int u,v,next;}e[M*2]={0}; int head[M]={0},Use=0; 7 void add(int x,int y,int z){Use++;e[Use].u=y;e[Use].v=z;e[Use].next=head[x];head[x]=Use;} 8 9 int use=1; 10 struct trie{int a[2];}a[M*30]={0}; 11 void add(int x){ 12 int now=1; 13 for(int i=30;~i;i--){ 14 bool k=(1<<i)&x; 15 if(a[now].a[k]) now=a[now].a[k]; 16 else a[now].a[k]=++use,a[use].a[0]=a[use].a[1]=0,now=use; 17 } 18 } 19 int query(int x){ 20 int now=1,res=0; 21 for(int i=30;~i;i--){ 22 bool k=(1<<i)&x; 23 if(a[now].a[k^1]) now=a[now].a[k^1],res+=(1<<i); 24 else now=a[now].a[k]; 25 } 26 return res; 27 } 28 29 int siz[M]={0},vis[M]={0}; 30 int minn=INF,minid=0; 31 void dfssiz(int x,int fa){ 32 siz[x]=1; 33 for(int i=head[x];i;i=e[i].next) 34 if(e[i].u!=fa&&vis[e[i].u]==0) 35 dfssiz(e[i].u,x),siz[x]+=siz[e[i].u]; 36 } 37 void dfsmax(int x,int fa,int fsiz){ 38 int maxn=fsiz-siz[x]; 39 for(int i=head[x];i;i=e[i].next) 40 if(e[i].u!=fa&&vis[e[i].u]==0){ 41 dfsmax(e[i].u,x,fsiz); 42 maxn=max(maxn,siz[e[i].u]); 43 } 44 if(maxn<minn) minn=maxn,minid=x; 45 } 46 int makeroot(int x){ 47 dfssiz(x,0); 48 minn=INF; minid=0; 49 dfsmax(x,0,siz[x]); 50 return minid; 51 } 52 53 int ans[M]={0},now[M]={0}; 54 void upans(int x,int fa,int Val){ 55 int hh=query(Val); 56 now[x]=hh; 57 for(int i=head[x];i;i=e[i].next) 58 if(e[i].u!=fa&&vis[e[i].u]==0){ 59 upans(e[i].u,x,Val^e[i].v); 60 now[x]=max(now[x],now[e[i].u]); 61 } 62 ans[x]=max(ans[x],now[x]); 63 } 64 void addtrie(int x,int fa,int Val){ 65 add(Val); 66 for(int i=head[x];i;i=e[i].next) 67 if(e[i].u!=fa&&vis[e[i].u]==0){ 68 addtrie(e[i].u,x,Val^e[i].v); 69 } 70 } 71 72 stack<int> s; 73 void dfs(int x){ 74 x=makeroot(x); vis[x]=1; 75 76 a[1].a[0]=a[1].a[1]=0; use=1; 77 add(0); 78 for(int i=head[x];i;i=e[i].next) if(vis[e[i].u]==0){ 79 upans(e[i].u,x,e[i].v); 80 ans[x]=max(ans[x],now[e[i].u]); 81 addtrie(e[i].u,x,e[i].v); 82 s.push(i); 83 } 84 85 a[1].a[0]=a[1].a[1]=0; use=1; 86 add(0); 87 while(!s.empty()){ 88 int i=s.top(); s.pop(); 89 upans(e[i].u,x,e[i].v); 90 ans[x]=max(ans[x],now[e[i].u]); 91 addtrie(e[i].u,x,e[i].v); 92 } 93 94 for(int i=head[x];i;i=e[i].next) if(vis[e[i].u]==0) 95 dfs(e[i].u); 96 } 97 98 int main(){ 99 int n; scanf("%d",&n); 100 for(int i=1;i<n;i++){ 101 int x,y,z; scanf("%d%d%d",&x,&y,&z); 102 add(x,y,z); add(y,x,z); 103 } 104 dfs(1); 105 for(int i=1;i<=n;i++) printf("%d\n",ans[i]); 106 }