[hdu 4757] Tree
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[hdu 4757] Tree相关的知识,希望对你有一定的参考价值。
Tree
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 102400/102400 K (Java/Others)
Total Submission(s): 2117 Accepted Submission(s): 634
The first line contains two integers n(1<=n<=10^5) and m(1<=m<=10^5), which are the amount of tree’s nodes and queries, respectively.
The second line contains n integers a[1..n] and a[i](0<=a[i]<2^{16}) is the value on the ith node.
The next n–1 lines contains two integers u v, which means there is an connection between u and v.
The next m lines contains three integers x y z, which are the parameters of Zero’s query.
3 2
1 2 2
1 2
2 3
1 3 1
2 3 2
题目意思就是给你一棵树,每个点都有一个点权,然后给你m个询问,每个询问有三个数x,y,z,表示求出从x到y的简单路径上面的点中,点权^z最大的是多少。
显然要用到trie,但是看起来很难的样子。。。我们不知道到底x,y是多少,而且我们也不可能对于每一对x,y路径上的点都建立一棵字典树,那怎么办办???
要用到可持久化数据结构。Persistant Trie!!!
就像主席树那样(然而我并不会),对于每一个节点要记录一个根节点ro[i],这个ro不再一定是1了,因为它需要做到可持久化,所以它可以是其他。
由于可持久化trie似乎有很多写法,所以就不讲写法了(我也不会讲,不是特别熟悉)。
对于这题,主要要注意的是,在insert的时候,要将节点x的父节点的信息下传(也就是说sz[x]表示大小前缀和)。
由于sz[x]+sz[y]-2*sz[lca(x,y)]>=0,我们就以这个条件来在query的时候继续向下访问。
1 %:pragma gcc optimize(2) 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define M(a,x) memset(a,x,sizeof a) 6 #define jug(i,x) (((1<<i)&x)>0) 7 using namespace std; 8 const int N=100005,ML=17,MN=1700005; 9 int n,Q,tot,ans; 10 int a[N],lnk[N],nxt[N*2],son[N*2]; 11 int dep[N],fa[N][ML]; 12 int LCA(int x,int y){ 13 if (dep[x]<dep[y]) swap(x,y); 14 int dif=dep[x]-dep[y]; 15 for (int i=ML-1; i>=0; i--) if (jug(i,dif)) x=fa[x][i]; 16 if (x==y) return x; 17 for (int i=ML-1; i>=0; i--) 18 if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; 19 return fa[x][0]; 20 } 21 struct Persistent_Trie{ 22 int ch[MN][2],sz[MN],ro[N]; 23 void init() {M(sz,0),M(ro,0);} 24 int newnode() { 25 M(ch[tot],0),sz[tot]=0; 26 return tot++; 27 } 28 void insert(int x,int y,int v) { 29 x=ro[x],y=ro[y]; 30 for (int i=15; i>=0; i--) { 31 bool c=jug(i,v); 32 if (!ch[x][c]) { 33 int idx=newnode(); 34 ch[x][c]=idx,ch[x][!c]=ch[y][!c]; 35 sz[ch[x][c]]=sz[ch[y][c]]; 36 } 37 x=ch[x][c],y=ch[y][c],sz[x]++; 38 } 39 } 40 int query(int x,int y,int v) { 41 int z=LCA(x,y),ret=a[z]^v,re=0; 42 x=ro[x],y=ro[y],z=ro[z]; 43 for (int i=15; i>=0; i--) { 44 bool c=jug(i,v); 45 if (sz[ch[x][!c]]+sz[ch[y][!c]]-2*sz[ch[z][!c]]>0) 46 re+=1<<i,c=!c; 47 x=ch[x][c],y=ch[y][c],z=ch[z][c]; 48 } 49 return max(ret,re); 50 } 51 }pt; 52 inline int read() { 53 int x=0; char ch=getchar(); 54 while (ch<‘0‘||ch>‘9‘) ch=getchar(); 55 while (ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar(); 56 return x; 57 } 58 void add(int x,int y) { 59 nxt[++tot]=lnk[x],son[tot]=y,lnk[x]=tot; 60 } 61 void DFS(int x,int y) { 62 fa[x][0]=y,dep[x]=dep[y]+1; 63 pt.ro[x]=pt.newnode(); 64 pt.insert(x,y,a[x]); 65 for (int j=lnk[x]; j; j=nxt[j]) 66 if (son[j]!=y) DFS(son[j],x); 67 } 68 int main() { 69 while (scanf("%d%d",&n,&Q)!=EOF) { 70 tot=0,M(lnk,0),M(nxt,0),M(fa,0),pt.init(); 71 for (int i=1; i<=n; i++) a[i]=read(); 72 for (int i=1; i<n; i++) { 73 int x=read(),y=read(); 74 add(x,y),add(y,x); 75 } 76 dep[0]=0,tot=1,DFS(1,0); 77 for (int j=1; j<ML; j++) 78 for (int i=1; i<=n; i++) fa[i][j]=fa[fa[i][j-1]][j-1]; 79 for (; Q; Q--){ 80 int x=read(),y=read(),z=read(); 81 printf("%d\n",pt.query(x,y,z)); 82 } 83 } 84 return 0; 85 }
(讲的可能非常不清楚,希望readers能够及时纠正里面可能存在的错误和漏洞,感谢!)
以上是关于[hdu 4757] Tree的主要内容,如果未能解决你的问题,请参考以下文章