zoukankan      html  css  js  c++  java
  • luogu2633 Count on a tree(树上LCA+主席树求区间第k小)

    传送:

    https://www.luogu.org/problem/P2633

    题意:

    给定一棵$N$个节点的树,每个点有一个权值,对于$M$个询问$(u,v,k)$,你需要回答$u xor lastans$和$v$这两个节点间第$K$小的点权。其中$lastans$是上一个询问的答案,初始为0,即第一个询问的u是明文。

    数据范围:

    $1<=n,m<=1e5$。

    分析:

    一维状态下的求区间第k小,用主席树维护,$n$棵树代表$n$个下标(位置),那么对于树上的结构怎么表示先后关系呢?

    很容易想到父亲与儿子,那么可以建立$n$棵树,儿子的树是在父亲的树的基础上建立的。因为从根节点出发,一定会经过父亲到达某个点。

    对于$u$到$v$的路径上的答案,可以表示为:

    $num[u]-num[lca(u,v)]+num[v]-num[lca(u,v)]+num[lca(u,v)]-num[lca(lca(u,v))]$

    $=num[u]+num[v]-num[lca(u,v)]-num[lca(lca(u,v))]$。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=1e5+10;
     4 struct node{
     5     int to,nxt;
     6 }edge[maxn*2];
     7 struct node2{
     8     int l,r,num;
     9 }tree[maxn*70];
    10 int num=0,size=0,N,tot,a[maxn],refl[maxn],head[maxn],fa[maxn][30],deep[maxn],root[maxn];
    11 void add(int x,int y){
    12     edge[++num]={y,head[x]};head[x]=num;
    13 }
    14 void update(int &x,int y,int l,int r,int dex){
    15     x=++size;tree[x]=tree[y];tree[x].num++;
    16     if (l==r) return ;
    17     int mid=(l+r)>>1;
    18     if (dex<=mid) update(tree[x].l,tree[y].l,l,mid,dex);
    19     else update(tree[x].r,tree[y].r,mid+1,r,dex);
    20 }
    21 int LCA(int x,int y){
    22     if (deep[x]>deep[y]) swap(x,y);
    23     for (int j=N;j>=0;j--)
    24         if (deep[x]<deep[y] && deep[fa[y][j]]>=deep[x]) y=fa[y][j];
    25     if (x==y) return x;
    26     for (int j=N;j>=0;j--)
    27         if (fa[x][j]!=fa[y][j]){
    28             x=fa[x][j];y=fa[y][j];
    29         }
    30     return fa[x][0];
    31 }
    32 int query(int x,int y,int fa1,int fa2,int l,int r,int kk){
    33     if (l==r) return l;
    34     int mid=(l+r)>>1;
    35     int tmp=tree[tree[x].l].num+tree[tree[y].l].num-tree[tree[fa1].l].num-tree[tree[fa2].l].num;
    36     if (tmp>=kk) return query(tree[x].l,tree[y].l,tree[fa1].l,tree[fa2].l,l,mid,kk);
    37     else return query(tree[x].r,tree[y].r,tree[fa1].r,tree[fa2].r,mid+1,r,kk-tmp);
    38 }
    39 void dfs(int x,int faa){
    40     int dex=lower_bound(refl+1,refl+1+tot,a[x])-refl;
    41     update(root[x],root[faa],1,tot,dex);
    42     fa[x][0]=faa; deep[x]=deep[faa]+1;
    43     for (int i=1;(1<<i)<=deep[x];i++)
    44         fa[x][i]=fa[fa[x][i-1]][i-1];
    45     for (int i=head[x];i!=-1;i=edge[i].nxt){
    46         int tmp=edge[i].to;
    47         if (tmp==faa) continue;
    48         dfs(tmp,x);
    49     } 
    50 }
    51 void init(int n){
    52     for (int i=0;i<=n;i++) head[i]=-1;
    53     num=0;size=0;deep[0]=0;
    54     N=floor(log(1.0*n)/log(2.0));
    55 }
    56 int main(){
    57     int n,m,x,y,k;scanf("%d%d",&n,&m);
    58     init(n);
    59     for (int i=1;i<=n;i++){
    60         scanf("%d",&a[i]);
    61         refl[i]=a[i];
    62     }
    63     sort(refl+1,refl+1+n);
    64     tot=unique(refl+1,refl+1+n)-(refl+1);
    65     for (int i=1;i<=n-1;i++){
    66         scanf("%d%d",&x,&y);
    67         add(x,y); add(y,x);
    68     }
    69     dfs(1,0);
    70     int Lans=0;
    71     while(m--){
    72         scanf("%d%d%d",&x,&y,&k);
    73         x^=Lans; int _lca=LCA(x,y);
    74         int tmp=query(root[x],root[y],root[_lca],root[fa[_lca][0]],1,tot,k);
    75         printf("%d
    ",Lans=refl[tmp]);
    76     } 
    77     return 0;
    78 }
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=1e5+10;
     4 struct node{
     5     int to,nxt;
     6 }edge[maxn*2];
     7 struct node2{
     8     int l,r,num;
     9 }tree[maxn*70];
    10 int num=0,size=0,N,tot,a[maxn],refl[maxn],head[maxn],fa[maxn][30],deep[maxn],root[maxn];
    11 void add(int x,int y){
    12     edge[++num]={y,head[x]};head[x]=num;
    13 }
    14 void update(int &x,int y,int l,int r,int dex){
    15     x=++size;tree[x]=tree[y];tree[x].num++;
    16     if (l==r) return ;
    17     int mid=(l+r)>>1;
    18     if (dex<=mid) update(tree[x].l,tree[y].l,l,mid,dex);
    19     else update(tree[x].r,tree[y].r,mid+1,r,dex);
    20 }
    21 int LCA(int x,int y){
    22     if (deep[x]>deep[y]) swap(x,y);
    23     for (int j=N;j>=0;j--)
    24         if (deep[x]<deep[y] && deep[fa[y][j]]>=deep[x]) y=fa[y][j];
    25     if (x==y) return x;
    26     for (int j=N;j>=0;j--)
    27         if (fa[x][j]!=fa[y][j]){
    28             x=fa[x][j];y=fa[y][j];
    29         }
    30     return fa[x][0];
    31 }
    32 int query(int x,int y,int fa1,int fa2,int l,int r,int kk){
    33     if (l==r) return l;
    34     int mid=(l+r)>>1;
    35     int tmp=tree[tree[x].l].num+tree[tree[y].l].num-tree[tree[fa1].l].num-tree[tree[fa2].l].num;
    36     if (tmp>=kk) return query(tree[x].l,tree[y].l,tree[fa1].l,tree[fa2].l,l,mid,kk);
    37     else return query(tree[x].r,tree[y].r,tree[fa1].r,tree[fa2].r,mid+1,r,kk-tmp);
    38 }
    39 void dfs(int x,int faa){
    40     int dex=lower_bound(refl+1,refl+1+tot,a[x])-refl;
    41     update(root[x],root[faa],1,tot,dex);
    42     fa[x][0]=faa; deep[x]=deep[faa]+1;
    43     for (int i=1;(1<<i)<=deep[x];i++)
    44         fa[x][i]=fa[fa[x][i-1]][i-1];
    45     for (int i=head[x];i!=-1;i=edge[i].nxt){
    46         int tmp=edge[i].to;
    47         if (tmp==faa) continue;
    48         dfs(tmp,x);
    49     } 
    50 }
    51 void init(int n){
    52     for (int i=0;i<=n;i++) head[i]=-1;
    53     num=0;size=0;deep[0]=0;
    54     N=floor(log(1.0*n)/log(2.0));
    55 }
    56 int main(){
    57     int n,m,x,y,k;scanf("%d%d",&n,&m);
    58     init(n);
    59     for (int i=1;i<=n;i++){
    60         scanf("%d",&a[i]);
    61         refl[i]=a[i];
    62     }
    63     sort(refl+1,refl+1+n);
    64     tot=unique(refl+1,refl+1+n)-(refl+1);
    65     for (int i=1;i<=n-1;i++){
    66         scanf("%d%d",&x,&y);
    67         add(x,y); add(y,x);
    68     }
    69     dfs(1,0);
    70     int Lans=0;
    71     while(m--){
    72         scanf("%d%d%d",&x,&y,&k);
    73         x^=Lans; int _lca=LCA(x,y);
    74         int tmp=query(root[x],root[y],root[_lca],root[fa[_lca][0]],1,tot,k);
    75         printf("%d
    ",Lans=refl[tmp]);
    76     } 
    77     return 0;
    78 }

    PS。bzoj2588卡内存,主席树开*70就过了。

     

  • 相关阅读:
    多个自定义覆盖物注册点击事件,点击某个覆盖物后获得它的坐标
    C# 文件操作(全部) 追加、拷贝、删除、移动文件、创建目录 修改文件名、文件夹名
    如何添加EXEStealth 2.5x 壳
    PACS系统简易
    好用的后端模版
    E信通项目总结[转]
    平台型产品的设计思路[转]
    baidu思维脑图在线编辑器
    Web 前端攻防(2014版)-baidu ux前端研发部
    访谈标叔:给新人设计师的建议【转】
  • 原文地址:https://www.cnblogs.com/changer-qyz/p/11423860.html
Copyright © 2011-2022 走看看