Bzoj 2588: Spoj 10628. Count on a tree 主席树,离散化,可持久,倍增LCA
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2588
2588: Spoj 10628. Count on a tree
Time Limit: 12 Sec Memory Limit: 128 MBSubmit: 3584 Solved: 835
[Submit][Status][Discuss]
Description
给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权。其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文。
Input
第一行两个整数N,M。
第二行有N个整数,其中第i个整数表示点i的权值。
后面N-1行每行两个整数(x,y),表示点x到点y有一条边。
最后M行每行两个整数(u,v,k),表示一组询问。
Output
M行,表示每个询问的答案。
Sample Input
8 5
105 2 9 3 8 5 7 7
1 2
1 3
1 4
3 5
3 6
3 7
4 8
2 5 1
0 5 2
10 5 3
11 5 4
110 8 2
105 2 9 3 8 5 7 7
1 2
1 3
1 4
3 5
3 6
3 7
4 8
2 5 1
0 5 2
10 5 3
11 5 4
110 8 2
Sample Output
2
8
9
105
7
8
9
105
7
HINT
HINT:
N,M<=100000
暴力自重。。。
Source
题解:
在树上建主席树,记得最后一行后没有空格,否则PE.
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define MAXN 100010 4 struct node 5 { 6 int begin,end,next; 7 }edge[MAXN*2]; 8 struct NODE 9 { 10 int left,right; 11 }tree[MAXN*20]; 12 int cnt,Head[MAXN],n,SIZE,value[MAXN],pos[MAXN],deep[MAXN],P[MAXN][17],sum[MAXN*20],a[MAXN],val[MAXN],root[MAXN],tot; 13 bool vis[MAXN]; 14 void addedge(int bb,int ee) 15 { 16 edge[++cnt].begin=bb;edge[cnt].end=ee;edge[cnt].next=Head[bb];Head[bb]=cnt; 17 } 18 void addedge1(int bb,int ee) 19 { 20 addedge(bb,ee);addedge(ee,bb); 21 } 22 int read() 23 { 24 int s=0,fh=1;char ch=getchar(); 25 while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();} 26 while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();} 27 return s*fh; 28 } 29 void dfs1(int u) 30 { 31 int i,v; 32 SIZE++;value[SIZE]=u;pos[u]=SIZE; 33 vis[u]=true; 34 for(i=Head[u];i!=-1;i=edge[i].next) 35 { 36 v=edge[i].end; 37 if(vis[v]==false) 38 { 39 deep[v]=deep[u]+1; 40 P[v][0]=u; 41 dfs1(v); 42 } 43 } 44 } 45 void Ycl() 46 { 47 int i,j; 48 for(j=1;(1<<j)<=n;j++) 49 { 50 for(i=1;i<=n;i++) 51 { 52 if(P[i][j-1]!=-1)P[i][j]=P[P[i][j-1]][j-1]; 53 } 54 } 55 } 56 int LCA(int x,int y) 57 { 58 int i,j; 59 if(deep[x]<deep[y])swap(x,y); 60 for(i=0;(1<<i)<=deep[x];i++);i--; 61 for(j=i;j>=0;j--)if(deep[x]-(1<<j)>=deep[y])x=P[x][j]; 62 if(x==y)return x; 63 for(j=i;j>=0;j--) 64 { 65 if(P[x][j]!=-1&&P[x][j]!=P[y][j]) 66 { 67 x=P[x][j]; 68 y=P[y][j]; 69 } 70 } 71 return P[x][0]; 72 } 73 void Update(int x,int &y,int l,int r,int k) 74 { 75 y=++SIZE; 76 sum[y]=sum[x]+1; 77 if(l==r)return; 78 tree[y].left=tree[x].left;tree[y].right=tree[x].right; 79 int mid=(l+r)/2; 80 if(k<=mid)Update(tree[x].left,tree[y].left,l,mid,k); 81 else Update(tree[x].right,tree[y].right,mid+1,r,k); 82 } 83 int query(int l,int r,int A,int B,int C,int D,int k) 84 { 85 if(l==r)return l; 86 int mid=(l+r)/2,tmp=sum[tree[A].left]+sum[tree[B].left]-sum[tree[C].left]-sum[tree[D].left]; 87 if(k<=tmp)return query(l,mid,tree[A].left,tree[B].left,tree[C].left,tree[D].left,k); 88 else return query(mid+1,r,tree[A].right,tree[B].right,tree[C].right,tree[D].right,k-tmp); 89 } 90 int Query(int A,int B,int k) 91 { 92 int C=LCA(A,B),D=P[C][0]; 93 A=root[pos[A]];B=root[pos[B]];C=root[pos[C]];D=root[pos[D]]; 94 return query(1,tot,A,B,C,D,k); 95 } 96 int main() 97 { 98 int m,i,bb,ee,k,k1,lastans,U,V,K; 99 n=read();m=read(); 100 for(i=1;i<=n;i++)a[i]=val[i]=read(); 101 sort(val+1,val+n+1); 102 tot=unique(val+1,val+n+1)-(val+1); 103 memset(Head,-1,sizeof(Head));cnt=1; 104 for(i=1;i<n;i++) 105 { 106 bb=read();ee=read(); 107 addedge1(bb,ee); 108 } 109 memset(P,-1,sizeof(P));SIZE=0; 110 memset(value,0,sizeof(value));//树上每个编号的实际的点. 111 memset(pos,0,sizeof(pos));//每个点在树上的编号. 112 dfs1(1);Ycl(); 113 memset(root,0,sizeof(root)); 114 SIZE=0; 115 for(i=1;i<=n;i++)//i为树上的节点.(即i为每个点在树上的编号.) 116 { 117 k=value[i]; 118 k1=lower_bound(val+1,val+tot+1,a[k])-val; 119 Update(root[pos[P[k][0]]],root[i],1,tot,k1); 120 } 121 lastans=0; 122 for(i=1;i<=m;i++) 123 { 124 U=read();V=read();K=read(); 125 U^=lastans; 126 lastans=val[Query(U,V,K)]; 127 printf("%d",lastans); 128 if(i!=m)printf("\n"); 129 } 130 fclose(stdin); 131 fclose(stdout); 132 return 0; 133 }