[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 }
View Code
原文地址:https://www.cnblogs.com/PYWBKTDA/p/11249686.html