[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


Problem Description
  Zero and One are good friends who always have fun with each other. This time, they decide to do something on a tree which is a kind of graph that there is only one path from node to node. First, Zero will give One an tree and every node in this tree has a value. Then, Zero will ask One a series of queries. Each query contains three parameters: x, y, z which mean that he want to know the maximum value produced by z xor each value on the path from node x to node y (include node x, node y). Unfortunately, One has no idea in this question. So he need you to solve it.
 

 

Input
  There are several test cases and the cases end with EOF. For each case:

  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.
 

 

Output
  For each query, output the answer.
 

 

Sample Input

3 2
1 2 2
1 2
2 3
1 3 1
2 3 2

 

Sample Output
3
0
 

 

Source
 
 

题目意思就是给你一棵树,每个点都有一个点权,然后给你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 }
View Code

(讲的可能非常不清楚,希望readers能够及时纠正里面可能存在的错误和漏洞,感谢!)

转载于:https://www.cnblogs.com/whc200305/p/7501840.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值