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
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
联系到在树上求两点之间的距离就是两个点到根的距离之和减去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 }