• [虚树][树状数组][lca] Jzoj P5908 开荒


    Description

    题目背景:
    尊者神高达作为一个萌新,在升级路上死亡无数次后被一只大黄叽带回了师门。他加入师门后发现有无穷无尽的师兄弟姐妹,这几天新副本开了,尊者神高达的师门作为一个 pve师门,于是他们决定组织一起去开荒。

    题目描述:
    师门可以看做以 1 为根的一棵树,师门中的每一个人都有一定的装备分数。一共会有 q 个事件。每个事件可能是一次开荒,也可能是因为开荒出了好装备而导致一个人的装分出现了变化。对于一次开荒,会有 k 个人组织,由于师门的号召力很强,所以所有在组织者中任意两个人简单路径上的人都会参加。
     

    Input

    第一行 n ,q;
    接下来 1 行 n 个数,代表每个人的分值;
    接下来 n-1 行 u,v 代表一条边
    接下来 q 行
    Q 代表询问,接下来 k 个数代表组织的人数,读入为 0时停止读入。
    C 代表修改,输入 x,w 代表将 x 的分值变为 w

    Output

    共 Q 的数量行,为开荒的人的总分值
     

    Sample Input

    4 4
    10 5 2 2
    1 2
    2 3
    2 4
    Q 3 4 0
    C 3 200
    Q 3 4 0
    Q 1 4 0

    Sample Output

    9
    207
    17
    
    样例解释:
    第一次询问,参加的人有 2,3,4 5+2+2=9
    第一次修改,权值为 10 5 200 2
    第二次询问,参加的人有 2,3,4 5+200+2=207
    第三次询问,参加的人有 1,2,4 10+5+2=17
     

    Data Constraint

    数据范围:
    20%的数据 n<=10000,q<=500;
    另外 20%的数据 k=2
    另外 20%的数据 没有修改操作
    所有数据 n,q<=100000,所有询问 k 的和<=1000000
    保证数据合法

    题解

    • 题目大意,有q次操作,询问操作是求k个点两两到lca所经过点的点权和,修改操作就是修改一个点的点权
    • 首先,求距离可以用树状数组按照dfs序加入,类似差分约束一样求
    • 当然修改也可以
    • 那么现在问题就是直接暴力两两lca做显然不行,要找一种更快的做法
    • 可以建一棵虚树
    • 然后对于虚树上的非父亲节点,直接求出他到父亲的点权和(不包括父亲),而对于父亲则直接加上自己的点权即可

    代码

     1 #include <cstdio> 
     2 #include <iostream>
     3 #include <algorithm>
     4 #include <cstring>
     5 using namespace std;
     6 const int N=2e5+10;
     7 int n,Q,tot,num,cnt,p,w,head[N],v[N],be[N],en[N],fa[N],d[N],dep[N],f[N][20],k[N],q[N];
     8 long long sz[N],ans;
     9 struct edge {int to,from;}e[N];
    10 void dfs(int x,int pre)
    11 {
    12     f[x][0]=fa[x]=pre,be[x]=++tot,d[x]=d[fa[x]]+1,dep[x]=dep[pre]+1;
    13     for (int i=head[x];i;i=e[i].from) if (e[i].to!=pre) dfs(e[i].to,x);
    14     en[x]=tot;
    15 }
    16 bool cmp(int x,int y) { return be[x]<be[y]; }
    17 int getlca(int x,int y)
    18 {
    19     if (dep[x]<dep[y]) swap(x,y);
    20     for (int i=18;i>=0;i--) if (dep[f[x][i]]>=dep[y]) x=f[x][i];
    21     if (x==y) return x;
    22     for (int i=18;i>=0;i--) if (f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
    23     return f[x][0];
    24 }
    25 void add(int x,int y) { for (;x<=n;x+=x&-x) sz[x]+=y; }
    26 long long getsum(int x)
    27 {
    28     long long v=0;
    29     for (;x;x-=x&-x) v+=sz[x];
    30     return v;
    31 }
    32 void insert(int x,int y) { e[++cnt].to=y; e[cnt].from=head[x]; head[x]=cnt; }
    33 int main()
    34 {
    35     //freopen("kaihuang.in","r",stdin),freopen("kaihuang.out","w",stdout);
    36     scanf("%d%d",&n,&Q);
    37     for (int i=1;i<=n;i++) scanf("%d",&v[i]);
    38     for (int i=1,x,y;i<n;i++) scanf("%d%d",&x,&y),insert(x,y),insert(y,x);
    39     dfs(1,0);
    40     for (int j=1;j<=19;j++) for (int i=1;i<=n;i++) f[i][j]=f[f[i][j-1]][j-1];
    41     for (int i=1;i<=n;i++) add(be[i],v[i]),add(en[i]+1,-v[i]);
    42     while (Q--)
    43     {
    44         scanf("
    ");
    45         char ch=getchar(); int x,y;
    46         if (ch=='C')
    47         {
    48             scanf("%d%d",&x,&y),y-=v[x],v[x]+=y;
    49             add(be[x],y),add(en[x]+1,-y);
    50         }
    51         else 
    52         {
    53             num=1,p=0; scanf("%d",&k[num]); while (k[num]!=0) scanf("%d",&k[++num]); num--;
    54             sort(k+1,k+num+1,cmp);
    55             w=num; for (int i=1;i<=w-1;i++) k[++num]=getlca(k[i],k[i+1]);
    56             sort(k+1,k+num+1,cmp),num=unique(k+1,k+num+1)-k-1;
    57             ans=0;
    58             for (int i=1;i<=num;i++)
    59             {
    60                 for (;p&&en[q[p]]<be[k[i]];) p--;
    61                 ans+=p?getsum(be[k[i]])-getsum(be[q[p]]):v[k[i]];
    62                 q[++p]=k[i];
    63             }
    64             printf("%lld
    ",ans);
    65         }
    66     }
    67 }
  • 相关阅读:
    对REST的理解
    longest-repeating-character-replacement(难)
    reconstruct-original-digits-from-english(好)
    third-maximum-number
    【好】strong-password-checker,我自己做出来的:)
    arithmetic-slices
    [poj 3159]Candies[差分约束详解][朴素的考虑法]
    POJ 2773 Happy 2006
    MySql安装(rpm)和启动配置
    [51daifan]来吧,一起书写51daifan的成长史吧-让一部分人先安全起来
  • 原文地址:https://www.cnblogs.com/Comfortable/p/9802591.html
Copyright © 2020-2023  润新知