2588: Spoj 10628. 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
 
联系到在树上求两点之间的距离就是两个点到根的距离之和减去lca到根的距离,我们可以将每个点到根的权值建立n个序列,我们会发现,这些序列中有重复的部分,准确来说,每个点都是这个点的父亲的序列后加了一个这个点的权值,我们考虑使用可持久化线段树,然后就好了。。。。
  1 #include<iostream>
  2 #include<cstdlib>
  3 #include<cmath>
  4 #include<cstring>
  5 #include<cstdio>
  6 #include<algorithm>
  7 #include<string>
  8 #include<map>
  9 #include<queue>
 10 #include<vector>
 11 #include<set>
 12 #define inf 1000000000
 13 #define maxn 100000+5
 14 #define maxm 2000000+5
 15 #define eps 1e-10
 16 #define ll long long
 17 #define for0(i,n) for(int i=0;i<=(n);i++)
 18 #define for1(i,n) for(int i=1;i<=(n);i++)
 19 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
 20 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
 21 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go)
 22 using namespace std;
 23 int read(){
 24     int x=0,f=1;char ch=getchar();
 25     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 26     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
 27     return x*f;
 28 }
 29 struct edge{
 30     int go,next;
 31 }e[2*maxn];
 32 struct data{
 33     int w,id;
 34 }a[maxn];
 35 int n,m,sz,tot,b[maxn],head[maxn];
 36 int s[maxm],ls[maxm],rs[maxm],root[maxn],f[maxn][18],dep[maxn];
 37 bool v[maxn];
 38 void ins(int x,int y){
 39     e[++tot]=(edge){y,head[x]};head[x]=tot;
 40     e[++tot]=(edge){x,head[y]};head[y]=tot;
 41 }
 42 void insert(int l,int r,int x,int &y,int v){
 43     y=++sz;
 44     s[y]=s[x]+1;
 45     if(l==r)return;
 46     ls[y]=ls[x];rs[y]=rs[x];
 47     int mid=(l+r)>>1;
 48     if(v<=mid)insert(l,mid,ls[x],ls[y],v);
 49     else insert(mid+1,r,rs[x],rs[y],v);
 50 }
 51 void dfs(int x){
 52     for1(i,17)
 53         if((1<<i)<=dep[x])f[x][i]=f[f[x][i-1]][i-1];else break;
 54     for4(i,x)
 55         if(!dep[y]){
 56             dep[y]=dep[x]+1;
 57             f[y][0]=x;
 58             insert(1,n,root[x],root[y],b[y]);
 59             dfs(y);
 60         }
 61 }
 62 int lca(int x,int y){
 63     if(dep[x]<dep[y])swap(x,y);
 64     int t=dep[x]-dep[y];
 65     for0(i,17)
 66         if(t&(1<<i))x=f[x][i];
 67     if(x==y)return x;
 68     for3(i,17,0)
 69         if(f[x][i]!=f[y][i])
 70             x=f[x][i],y=f[y][i];
 71     return f[x][0];
 72 }
 73 int query(int l,int r,int x,int y,int xx,int yy,int k){
 74     if(l==r)return l;
 75     int mid=(l+r)>>1,tmp=s[ls[x]]+s[ls[y]]-s[ls[xx]]-s[ls[yy]];
 76     if(tmp>=k)return query(l,mid,ls[x],ls[y],ls[xx],ls[yy],k);
 77     else return query(mid+1,r,rs[x],rs[y],rs[xx],rs[yy],k-tmp);
 78 }
 79 bool cmp(data x,data y){
 80     return x.w<y.w;
 81 }
 82 int main(){
 83     //freopen("input.txt","r",stdin);
 84     //freopen("output.txt","w",stdout);
 85     n=read();m=read();
 86     for1(i,n)a[i].w=read(),a[i].id=i;
 87     sort(a+1,a+n+1,cmp);
 88     for1(i,n)b[a[i].id]=i;
 89     for1(i,n-1){
 90         int x=read(),y=read();
 91         ins(x,y);
 92     }
 93     ins(0,1);
 94     dep[0]=1;
 95     dfs(0);
 96     int ans=0;
 97     for1(i,m){
 98         int x=read(),y=read(),k=read();x^=ans;
 99         ans=a[query(1,n,root[x],root[y],root[lca(x,y)],root[f[lca(x,y)][0]],k)].w;
100         printf("%d",ans);
101         if(i!=m)printf("\n");
102     }
103     return 0;
104 }
View Code

 

posted @ 2016-07-05 11:29  HTWX  阅读(108)  评论(0编辑  收藏  举报