bzoj2588 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
N,M<=100000
暴力自重。。。
正解:树上主席树
利用树上前缀和的思想来进行主席树的操作,用dfs序存储每个结点的信息,然后就是道主席树版子题了。。
1 //It is made by wfj_2048~ 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 #include <cstdlib> 6 #include <cstdio> 7 #include <vector> 8 #include <cmath> 9 #include <queue> 10 #include <stack> 11 #include <map> 12 #include <set> 13 #define inf 1<<30 14 #define il inline 15 #define RG register 16 #define ll long long 17 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) 18 19 using namespace std; 20 21 struct edge{ int nt,to; }g[200010]; 22 23 int head[100010],size[100010],dep[100010],dfn[100010],top[100010],fa[100010],son[100010],a[100010],num[100010],hashh[100010],root[100010],sum[5000010],ls[5000010],rs[5000010],m,n,N,sz,tot,cnt,pre; 24 25 il int gi(){ 26 RG int x=0,q=0; RG char ch=getchar(); 27 while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); if (ch=='-') q=1,ch=getchar(); 28 while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q ? -x : x; 29 } 30 31 il void ins(RG int from,RG int to){ g[++N]=(edge){head[from],to},head[from]=N; return; } 32 33 il void insert(RG int l,RG int r,RG int x,RG int &y,RG int v){ 34 y=++sz,sum[y]=sum[x]+1; if (l==r) return; ls[y]=ls[x],rs[y]=rs[x]; RG int mid=(l+r)>>1; 35 if (v<=mid) insert(l,mid,ls[x],ls[y],v); else insert(mid+1,r,rs[x],rs[y],v); return; 36 } 37 38 il void dfs1(RG int x,RG int p){ 39 dfn[x]=++cnt,dep[x]=dep[p]+1,fa[x]=p,size[x]=1; RG int v,mx=0; 40 for (RG int i=head[x];i;i=g[i].nt){ 41 v=g[i].to; if (v==p) continue; dfs1(v,x); 42 size[x]+=size[v]; if (size[mx]<size[v]) mx=v; 43 } 44 son[x]=mx; return; 45 } 46 47 il void dfs2(RG int x,RG int p,RG int anc){ 48 insert(1,tot,root[dfn[p]],root[dfn[x]],lower_bound(hashh+1,hashh+tot+1,a[x])-hashh); 49 top[x]=anc; if (son[x]) dfs2(son[x],x,anc); RG int v; 50 for (RG int i=head[x];i;i=g[i].nt){ 51 v=g[i].to; if (v==p || v==son[x]) continue; dfs2(v,x,v); 52 } 53 return; 54 } 55 56 il int lca(RG int u,RG int v){ 57 RG int t; while (top[u]!=top[v]){ if (dep[top[u]]<dep[top[v]]) t=u,u=v,v=t; u=fa[top[u]]; } 58 if (dep[u]<dep[v]) return u; else return v; 59 } 60 61 il int query(RG int a,RG int b,RG int k){ 62 RG int c=lca(a,b),d=fa[c],L=1,R=tot,mid,tmp; 63 a=root[dfn[a]],b=root[dfn[b]],c=root[dfn[c]],d=root[dfn[d]]; 64 while (L<R){ 65 mid=(L+R)>>1,tmp=sum[ls[a]]+sum[ls[b]]-sum[ls[c]]-sum[ls[d]]; 66 if (k<=tmp) R=mid,a=ls[a],b=ls[b],c=ls[c],d=ls[d]; 67 else L=mid+1,k-=tmp,a=rs[a],b=rs[b],c=rs[c],d=rs[d]; 68 } 69 return hashh[L]; 70 } 71 72 il void work(){ 73 n=gi(),m=gi(); for (RG int i=1;i<=n;++i) num[i]=a[i]=gi(); 74 for (RG int i=1;i<n;++i){ RG int u=gi(),v=gi(); ins(u,v),ins(v,u); } sort(num+1,num+n+1); 75 hashh[++tot]=num[1]; for (RG int i=2;i<=n;++i) if (num[i]!=num[i-1]) hashh[++tot]=num[i]; 76 dfs1(1,0),dfs2(1,0,1); 77 for (RG int i=1;i<=m;++i){ 78 RG int u=gi(),v=gi(),k=gi(); pre=query(u^pre,v,k); 79 printf("%d",pre); if (i!=m) printf("\n"); 80 } 81 return; 82 } 83 84 int main(){ 85 File("chairtree"); 86 work(); 87 return 0; 88 }