• [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
  • 相关阅读:
    照片墙效果一多实例演示【已封装】
    把javascript event事件封装了下,兼容大多数浏览器
    catch error
    call tcl from c
    scrollbar
    sharedlibextension
    treectrl
    get file name part
    namespace eval
    glob
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/11249686.html
Copyright © 2020-2023  润新知