• 【9018:2221】[伪模板]可持久化线段树


    2221: [伪模板]可持久化线段树

    时间限制: 1 Sec 内存限制: 130 MB
    提交: 29 解决: 11
    [提交][状态][讨论版]

    题目描述

    小Z有一棵树,其名曰“可持久化线段树”,这棵树上有n个节点,每个节点有个权值,每1s,每个节点就会长出一个美味度为权值的果子,但是每个节点最多只会有一个果子,现在小Z打算花q秒的时间摘果子,他1s可以摘1个果子,每次摘的果子为两个点最简路径上的美味度第k小的果子,请你回答他的询问。

    输入

    第1行1个正整数n。

    接下来n-1行,每行2个数x,y表示x、y间有边相连;

    接下来1行,n个整数,表示每个节点的权值vi;

    接下来1行,1个正整数q.

    接下来q行,每行3个整数x,y,k表示,这1s,他摘得是x,y最简路径上的第k小。

    输出

    输出q行,每行1个整数表示答案。

    样例输入

    8
    1 2
    1 3
    1 4
    4 8
    2 5
    2 6
    2 7
    3 5 2 4 1 8 3 6
    9
    5 7 2
    6 3 3
    7 8 5
    3 2 2
    2 4 3
    1 8 2
    1 8 1
    1 8 3
    2 3 3

    样例输出

    3
    5
    6
    3
    5
    4
    3
    6
    5
    

    提示

    1<=n,q<=200000 1<=x,y,vi<=n 保证数据合法(是一棵树,且第k小存在)

     题解:树上的主席树,答案为f[fa[lca(x,y)]]+f[lca(x,y)]-f[x]-f[y],注意数值可能重复。

    代码如下:

     1 #include<cstdio>
     2 #include<iostream>
     3 #define MN 200005
     4 #define MM 5000005
     5 using namespace std;
     6 int n,m,v[MN],ct,h[MN],cnt,ls[MM],rs[MM],T[MM],rt[MM];
     7 int mn=0x7fffffff,mx=-1,dep[MN],fa[MN],sz[MN],son[MN],top[MN];
     8 struct node{int to,nxt;}e[2*MN];
     9 void ins(int u,int v){e[++ct].to=v;e[ct].nxt=h[u];h[u]=ct;}
    10 void update(int &k,int l,int r,int ad){
    11     ls[++cnt]=ls[k],rs[cnt]=rs[k],T[cnt]=T[k],k=cnt;
    12     if(l==r){T[k]++;return;}
    13     int mid=(l+r)>>1;
    14     if(ad<=mid) update(ls[k],l,mid,ad);
    15     else update(rs[k],mid+1,r,ad);
    16     T[k]=T[ls[k]]+T[rs[k]];
    17 }
    18 int que(int k,int l,int r,int qll,int qlr,int qrl,int qrr){
    19     if(l==r) return l;
    20     int mid=(l+r)>>1;
    21     if(k<=T[ls[qrr]]+T[ls[qrl]]-T[ls[qll]]-T[ls[qlr]]) return que(k,l,mid,ls[qll],ls[qlr],ls[qrl],ls[qrr]);
    22     else return que(k-=T[ls[qrr]]+T[ls[qrl]]-T[ls[qll]]-T[ls[qlr]],mid+1,r,rs[qll],rs[qlr],rs[qrl],rs[qrr]); 
    23 }
    24 void dfs1(int u,int f,int d){
    25     dep[u]=d,fa[u]=f,sz[u]=1;
    26     rt[u]=rt[f],update(rt[u],mn,mx,v[u]);
    27     for(int i=h[u];i;i=e[i].nxt)if(e[i].to!=f){
    28         dfs1(e[i].to,u,d+1); sz[u]+=sz[e[i].to];
    29         if(sz[e[i].to]>sz[son[u]]) son[u]=e[i].to;
    30     }
    31 }
    32 void dfs2(int u,int tp){
    33     top[u]=tp; if(son[u]) dfs2(son[u],tp);
    34     for(int i=h[u];i;i=e[i].nxt)
    35         if(e[i].to!=fa[u]&&e[i].to!=son[u]) dfs2(e[i].to,e[i].to);
    36 }
    37 int lca(int x,int y){
    38     while(top[x]!=top[y])
    39         if(dep[top[x]]>dep[top[y]]) x=fa[top[x]];
    40         else y=fa[top[y]];
    41     return dep[x]>dep[y]?y:x;
    42 }
    43 int main()
    44 {
    45     scanf("%d",&n);
    46     for(int i=1;i<n;i++){
    47         int x,y; scanf("%d%d",&x,&y);
    48         ins(x,y); ins(y,x);
    49     }
    50     for(int i=1;i<=n;i++){
    51         scanf("%d",&v[i]);
    52         mx=max(mx,v[i]); mn=min(mn,v[i]);
    53     }
    54     dfs1(1,0,1); dfs2(1,1);
    55     scanf("%d",&m);
    56     for(int i=1;i<=m;i++){
    57         int x,y,z; scanf("%d%d%d",&x,&y,&z);
    58         int tmp=lca(x,y);
    59         printf("%d
    ",que(z,mn,mx,rt[fa[tmp]],rt[tmp],rt[x],rt[y]));
    60     }
    61 }
  • 相关阅读:
    2010浙大:zoj问题
    Meta 数据中文显示
    django 中间件
    url的配置
    django.contirb
    os模块
    线程和异步
    ADO.NET
    C#托管代码 CLR
    C#垃圾回收
  • 原文地址:https://www.cnblogs.com/Beginner-/p/8549989.html
Copyright © 2020-2023  润新知