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

Sample Output

2
8
9
105
7

HINT

 




HINT:

N,M<=100000

暴力自重。。。
 
思路: 

对于每个节点维护这个节点到根的权值线段树

对于每个询问(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 } 
View Code

 

posted @ 2019-02-22 14:05  zjxxcn  阅读(104)  评论(0编辑  收藏  举报