bzoj 2588 Count on a tree
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
暴力自重。。。
思路:
View Code
对于每个节点维护这个节点到根的权值线段树
对于每个询问(x,y),这条路径上的线段树
tree[x]+tree[y]-tree[lca(x,y)]-tree[fa[lca(x,y)]]
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define R register int 4 #define rep(i,a,b) for(R i=a;i<=b;i++) 5 #define Rep(i,a,b) for(R i=a;i>=b;i--) 6 #define ms(i,a) memset(a,i,sizeof(a)) 7 #define rp(i,x) for(R i=H[x];i!=-1;i=E[i].nt) 8 #define gc() getchar() 9 int const N=100000+5; 10 int const M=2000000+5; 11 template<class T>void read(T &x){ 12 x=0; char c=gc(); 13 while (!isdigit(c)) c=gc(); 14 while (isdigit(c)) x=x*10+(c^48),c=gc(); 15 } 16 int n,m,tot,cnt,ind,sz,last; 17 int tmp[N],hash[N],H[N],v[N]; 18 int num[N], pos[N],deep[N]; 19 int sum[M],lch[M],rch[M]; 20 int root[N],tin[N],tout[N]; 21 int f[N][17],S; 22 struct Edge{ 23 int to,nt; 24 }E[N<<1]; 25 void add(int a,int b){ 26 E[cnt]=(Edge){b,H[a]};H[a]=cnt++; 27 } 28 void dfs(int x,int fat){ 29 tin[x]=++S; f[x][0]=fat; 30 ind++; num[ind]=x; pos[x]=ind; 31 rp(i,x){ 32 int v=E[i].to; 33 if(v==fat) continue; 34 dfs(v,x); 35 } 36 tout[x]=++S; 37 } 38 int ancestor(int x,int y){ 39 return tin[x]<=tin[y] && tout[y]<=tout[x]; 40 } 41 int lca(int x,int y){ 42 if(ancestor(x,y)) return x; 43 if(ancestor(y,x)) return y; 44 Rep(i,16,0) if(!ancestor(f[x][i],y)) x=f[x][i]; 45 return f[x][0]; 46 } 47 void update(int l,int r,int x,int &y,int num){ 48 y=++sz; 49 sum[y]=sum[x]+1; 50 if(l==r) return; 51 lch[y]=lch[x],rch[y]=rch[x]; 52 int mid=(l+r)/2; 53 if(num<=mid) update(l,mid,lch[x],lch[y],num); 54 else update(mid+1,r,rch[x],rch[y],num); 55 } 56 int ask(int l,int r,int z,int a,int b,int c,int d){ 57 if(l==r) return tmp[r]; 58 int ct=sum[lch[a]]+sum[lch[b]]-sum[lch[c]]-sum[lch[d]]; 59 int mid=(l+r)/2; 60 if(ct>=z) return ask(l,mid,z,lch[a],lch[b],lch[c],lch[d]); 61 else return ask(mid+1,r,z-ct,rch[a],rch[b],rch[c],rch[d]); 62 } 63 int query(int x,int y,int z,int k){ 64 int t=lca(x,y); 65 int tt=f[t][0]; 66 if(t==1) tt=0; 67 int a=pos[x]; 68 int b=pos[y]; 69 int c=pos[t]; 70 int d=pos[tt]; 71 return ask(1,k,z,root[a],root[b],root[c],root[d]); 72 } 73 void q(int x,int l,int r){ 74 if(l==r) return; 75 int mid=(l+r)/2; 76 q(lch[x],l,mid); 77 q(rch[x],mid+1,r); 78 } 79 int main(){ 80 read(n); read(m); 81 rep(i,1,n) read(v[i]),tmp[i]=v[i]; 82 sort(tmp+1,tmp+n+1); 83 int k=unique(tmp+1,tmp+n+1)-tmp-1; 84 rep(i,1,n) v[i]=lower_bound(tmp+1,tmp+k+1,v[i])-tmp; 85 ms(-1,H); 86 rep(i,1,n-1){ 87 int x,y; 88 read(x); read(y); 89 add(x,y);add(y,x); 90 } 91 dfs(1,1); 92 rep(j,1,16) rep(i,1,n) f[i][j]=f[f[i][j-1]][j-1]; 93 rep(i,1,n){ 94 int t=num[i]; 95 int fa=f[t][0]; 96 if(t==1) fa=0; 97 update(1,k,root[pos[fa]],root[i],v[t]); 98 } 99 while (m--){ 100 int x,y,z; 101 read(x);read(y);read(z); 102 x^=last; 103 last=query(x,y,z,k); 104 printf("%d\n",last); 105 } 106 return 0; 107 }