• 洛谷——P3833 [SHOI2012]魔法树


    P3833 [SHOI2012]魔法树

    题目背景

    SHOI2012 D2T3

    题目描述

    Harry Potter 新学了一种魔法:可以让改变树上的果子个数。满心欢喜的他找到了一个巨大的果树,来试验他的新法术。

    这棵果树共有N个节点,其中节点0是根节点,每个节点u的父亲记为fa[u],保证有fa[u] < u。初始时,这棵果树上的果子都被 Dumbledore 用魔法清除掉了,所以这个果树的每个节点上都没有果子(即0个果子)。

    不幸的是,Harry 的法术学得不到位,只能对树上一段路径的节点上的果子个数统一增加一定的数量。也就是说,Harry 的魔法可以这样描述:

    Add u v d

    表示将点u和v之间的路径上的所有节点的果子个数都加上d。

    接下来,为了方便检验 Harry 的魔法是否成功,你需要告诉他在释放魔法的过程中的一些有关果树的信息:

    Query u

    表示当前果树中,以点u为根的子树中,总共有多少个果子?

    输入输出格式

    输入格式:

    第一行一个正整数N (1 ≤ N ≤ 100000),表示果树的节点总数,节点以0,1,…,N − 1标号,0一定代表根节点。

    接下来N − 1行,每行两个整数a,b (0 ≤ a < b < N),表示a是b的父亲。

    接下来是一个正整数Q(1 ≤ ? ≤ 100000),表示共有Q次操作。

    后面跟着Q行,每行是以下两种中的一种:

    1. A u v d,表示将u到v的路径上的所有节点的果子数加上d;0 ≤ u,v <N,0 < d < 100000

    2. Q u,表示询问以u为根的子树中的总果子数,注意是包括u本身的。

    输出格式:

    对于所有的Query操作,依次输出询问的答案,每行一个。答案可能会超过2^32 ,但不会超过10^15 。

    输入输出样例

    输入样例#1: 复制
    4
    0 1
    1 2
    2 3
    4
    A 1 3 1
    Q 0
    Q 1
    Q 2
    输出样例#1: 复制
    3
    3
    2

     

    树链剖分模板题,注意一下细节即可

    #include<bits/stdc++.h>
    
    #define N 1010100
    #define LL long long
    using namespace std;
    
    struct node {
        LL to,next;
    } e[N];
    struct tree {
        LL l,r,w,f;
    } tr[N];
    
    LL n,m,head[N],tot,ans;
    
    //(u,v)树上修改 
    //询问子树大小
    
    void add(LL u,LL v) {
        e[++tot].to=v,e[tot].next=head[u],head[u]=tot;
    }
    
    LL dep[N],siz[N],son[N],fa[N];
    void dfs(LL u,LL f,LL deep) {
        dep[u]=deep,siz[u]=1,fa[u]=f;
        LL maxson=-1;
        for(LL i=head[u]; i; i=e[i].next) {
            LL v=e[i].to;
            if(v==f) continue;
            dfs(v,u,deep+1);
            siz[u]+=siz[v];
            if(siz[v]>maxson) maxson=siz[v],son[u]=v;
        }
    }
    
    LL top[N],id[N],item;
    void dfs2(LL u,LL topf) {
        id[u]=++item,top[u]=topf;
        if(!son[u]) return;
        dfs2(son[u],topf);
        for(LL i=head[u]; i; i=e[i].next) {
            LL v=e[i].to;
            if(v==fa[u]||v==son[u]) continue;
            dfs2(v,v);
        }
    }
    
    void build(LL k,LL l,LL r) {
        tr[k].l=l,tr[k].r=r;
        if(l==r) return;
        LL mid=(l+r)/2;
        build(k*2,l,mid);
        build(k*2+1,mid+1,r);
    }
    
    void upda(LL k) {
        tr[k].w=tr[k*2].w+tr[k*2+1].w;
    }
    void down(LL k) {
        LL f=tr[k].f;
        tr[k].f=0;
        tr[k*2].w=(tr[k*2].w+f*(tr[k*2].r-tr[k*2].l+1));
        tr[k*2+1].w=(tr[k*2+1].w+f*(tr[k*2+1].r-tr[k*2+1].l+1));
        tr[k*2].f+=f,tr[k*2+1].f+=f;
    }
    
    void change_LLerval(LL k,LL l,LL r,LL p) {
        LL ll=tr[k].l,rr=tr[k].r,mid=(ll+rr)/2;
        if(ll>=l&&rr<=r) {
            tr[k].w=(tr[k].w+(rr-ll+1)*p);
            tr[k].f+=p;
            return;
        }
        if(tr[k].f) down(k);
        if(l<=mid) change_LLerval(k*2,l,r,p);
        if(r>mid) change_LLerval(k*2+1,l,r,p);
        upda(k);
    }
    
    void ask_LLerval(LL k,LL l,LL r) {
        LL ll=tr[k].l,rr=tr[k].r,mid=(ll+rr)/2;
        if(ll>=l&&rr<=r) {
            ans+=tr[k].w;
            return;
        }
        if(tr[k].f) down(k);
        if(l<=mid) ask_LLerval(k*2,l,r);
        if(r>mid) ask_LLerval(k*2+1,l,r);
        upda(k);
    }
    
    void change(LL a,LL b,LL p) {
        while(top[a]!=top[b]) {
            if(dep[top[a]]<dep[top[b]]) swap(a,b);
            change_LLerval(1,id[top[a]],id[a],p);
            a=fa[top[a]];
        }
        if(dep[a]<dep[b]) swap(a,b);
        change_LLerval(1,id[b],id[a],p);
    }
    
    LL sum(LL a) {
        ans=0;
        ask_LLerval(1,id[a],id[a]+siz[a]-1);
        return ans;
    }
    
    int main() {
        scanf("%lld",&n);
        for(LL a,b,i=1; i<n; i++) {
            scanf("%lld%lld",&a,&b);
            add(a+1,b+1);
        }
        dfs(1,0,1);
        dfs2(1,1);
        build(1,1,n);
        scanf("%lld",&m);
        for(LL a,b,c,i=1; i<=m; i++) {
            char x;
            cin>>x;
            if(x=='A') {
                scanf("%lld%lld%lld",&a,&b,&c);
                change(a+1,b+1,c);
            } else {
                scanf("%lld",&a);
                printf("%lld
    ",sum(a+1));
            }
        }
        return 0;
    }
  • 相关阅读:
    go语言切片
    sharding-jdbc分库分表配置,多数据源
    spring boot的配置文件
    go-micro生成项目
    自定义注解+aop实现jetcache功能扩展
    linux下mysql忘记密码解决方案
    MySQL 1130错误,无法远程连接
    Linux/UNIX 上安装 MySQL
    BarTender遇到的问题
    SourceTree安装使用
  • 原文地址:https://www.cnblogs.com/song-/p/9545192.html
Copyright © 2020-2023  润新知