[bzoj2588]Count on a tree
根据每一个点到根的每一个点的权值建立n颗权值线段树(也就是一颗可持久化线段树/主席树),然后查询操作相当于对F[x]+F[y]-F[lca(x,y)]-F[fa[lca(x,y)]]这颗线段树作查询。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define mid (l+r>>1) 4 #define N 200001 5 struct ji{ 6 int nex,to; 7 }edge[N<<1]; 8 int E,V,n,m,t,x,y,z,ans,a[N],f[21][N],head[N],sz[20*N],b[N],son[2][20*N],s[N],r[N]; 9 char s1[11]; 10 void add(int x,int y){ 11 edge[E].nex=head[x]; 12 edge[E].to=y; 13 head[x]=E++; 14 } 15 int ne(int &k){ 16 if (!k)k=++V; 17 return k; 18 } 19 int lca(int x,int y){ 20 if (s[x]<s[y])swap(x,y); 21 for(int i=20;i>=0;i--) 22 if (s[f[i][x]]>=s[y])x=f[i][x]; 23 if (x==y)return x; 24 for(int i=20;i>=0;i--) 25 if (f[i][x]!=f[i][y]){ 26 x=f[i][x]; 27 y=f[i][y]; 28 } 29 return f[0][x]; 30 } 31 void update(int k1,int k2,int l,int r,int x){ 32 sz[k1]=sz[k2]+1; 33 if (l==r)return; 34 int p=(x>mid); 35 son[p^1][k1]=son[p^1][k2]; 36 update(ne(son[p][k1]),son[p][k2],l+(mid-l+1)*p,mid+(r-mid)*p,x); 37 } 38 int query(int l,int r,int x,int a,int b,int c,int d){ 39 if (l==r)return l; 40 int t=sz[son[0][a]]+sz[son[0][b]]-sz[son[0][c]]-sz[son[0][d]],p=(x>t); 41 return query(l+(mid-l+1)*p,mid+(r-mid)*p,x-p*t,son[p][a],son[p][b],son[p][c],son[p][d]); 42 } 43 void dfs(int k,int fa){ 44 s[k]=s[f[0][k]=fa]+1; 45 for(int i=1;i<=20;i++)f[i][k]=f[i-1][f[i-1][k]]; 46 update(ne(r[k]),r[fa],1,m,a[k]); 47 for(int i=head[k];i!=-1;i=edge[i].nex) 48 if (edge[i].to!=fa)dfs(edge[i].to,k); 49 } 50 int main(){ 51 scanf("%d%d",&n,&t); 52 memset(head,-1,sizeof(head)); 53 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 54 memcpy(b,a,sizeof(b)); 55 sort(b+1,b+n+1); 56 m=unique(b+1,b+n+1)-b-1; 57 for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+m+1,a[i])-b; 58 for(int i=1;i<n;i++){ 59 scanf("%d%d",&x,&y); 60 add(x,y); 61 add(y,x); 62 } 63 dfs(1,0); 64 for(int i=1;i<=20;i++) 65 for(int j=1;j<=n;j++)f[i][j]=f[i-1][f[i-1][j]]; 66 while (t--){ 67 scanf("%d%d%d",&x,&y,&z); 68 x^=ans; 69 printf("%d\n",ans=b[query(1,m,z,r[x],r[y],r[lca(x,y)],r[f[0][lca(x,y)]])]); 70 } 71 }