[hdu 4757] Tree
阿新 • • 發佈:2017-09-10
註意 region one include hdu 字典 lca 最大 san
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.
Tree
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 102400/102400 K (Java/Others)
Total Submission(s): 2117 Accepted Submission(s): 634
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 2013 ACM/ICPC Asia Regional Nanjing Online
題目意思就是給你一棵樹,每個點都有一個點權,然後給你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能夠及時糾正裏面可能存在的錯誤和漏洞,感謝!)
[hdu 4757] Tree