• P3833 [SHOI2012]魔法树


    思路

    树剖板子
    注意给出点的编号是从零开始的

    代码

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #define int long long
    using namespace std;
    const int MAXN = 100100;
    int u[100100<<1],v[100100<<1],fir[100100],nxt[100100<<1],cnt;
    void addedge(int ui,int vi){
        ++cnt;
        u[cnt]=ui;
        v[cnt]=vi;
        nxt[cnt]=fir[ui];
        fir[ui]=cnt;
    }
    int fa[100100],top[100100],sz[100100],id[100100],dfs_clock,dep[100100],heason[100100],n;
    void dfs1(int u,int f){
        dep[u]=dep[f]+1;
        fa[u]=f;
        sz[u]=1;
        for(int i=fir[u];i;i=nxt[i]){
            if(v[i]==f)
                continue;
            dfs1(v[i],u);
            sz[u]+=sz[v[i]];
            if(heason[u]==0||sz[v[i]]>sz[heason[u]])
                heason[u]=v[i];
        }
    }
    void dfs2(int u,int topf){
        top[u]=topf;
        id[u]=++dfs_clock;
        if(!heason[u])
            return;
        dfs2(heason[u],topf);
        for(int i=fir[u];i;i=nxt[i]){
            if(v[i]==fa[u]||v[i]==heason[u])
                continue;
            dfs2(v[i],v[i]);
        }
    }
    int seg[100100<<2],tag[100100<<2];
    void pushup(int o){
        seg[o]=seg[o<<1]+seg[o<<1|1];
    }
    void pushdown(int o,int ln,int rn){
        if(tag[o]){
            seg[o<<1]+=tag[o]*ln;
            seg[o<<1|1]+=tag[o]*rn;
            tag[o<<1]+=tag[o];
            tag[o<<1|1]+=tag[o];
            tag[o]=0;
        }
    }
    void update(int L,int R,int l,int r,int o,int c){
        if(L<=l&&r<=R){
            seg[o]+=c*(r-l+1);
            tag[o]+=c;
            return;
        }
        int mid=(l+r)>>1;
        pushdown(o,mid-l+1,r-mid);
        if(L<=mid)
            update(L,R,l,mid,o<<1,c);
        if(R>mid)
            update(L,R,mid+1,r,o<<1|1,c);
        pushup(o);
    }
    int query(int L,int R,int l,int r,int o){
        if(L<=l&&r<=R){
            return seg[o];
        }
        int mid=(l+r)>>1,ans=0;
        pushdown(o,mid-l+1,r-mid);
        if(L<=mid)
            ans+=query(L,R,l,mid,o<<1);
        if(R>mid)
            ans+=query(L,R,mid+1,r,o<<1|1);
        return ans;
    }
    void update(int x,int y,int c){
        while(top[x]!=top[y]){
            if(dep[top[x]]<dep[top[y]])
                swap(x,y);
            update(id[top[x]],id[x],1,n,1,c);
            x=fa[top[x]];
        }
        if(dep[x]>dep[y])
            swap(x,y);
        update(id[x],id[y],1,n,1,c);
    }
    int query(int x){
        return query(id[x],id[x]+sz[x]-1,1,n,1);
    }
    signed main(){
        scanf("%lld",&n);
        for(int i=1;i<n;i++){
            int a,b;
            scanf("%lld %lld",&a,&b);
            a++;
            b++;
            addedge(a,b);
            addedge(b,a);
        }
        dfs1(1,0);
        dfs2(1,1);
        int q;
        scanf("%lld",&q);
        for(int i=1;i<=q;i++){
            char c=getchar();
            while(c!='Q'&&c!='A')
                c=getchar();
            if(c=='A'){
                int a,b,c;
                scanf("%lld %lld %lld",&a,&b,&c);
                a++;
                b++;
                update(a,b,c);
            }
            else{
                int a;
                scanf("%lld",&a);
                a++;
                printf("%lld
    ",query(a));
            }
        }
        return 0;
    }
    
  • 相关阅读:
    shell函数
    sed命令
    交互式输入与for语句
    day01_云计算概述及kvm介绍
    grep与正则表达式
    shell的编程原理
    shell的文本处理工具
    shell的基础入门
    深入理解JavaScript中 fn() 和 return fn() 的区别
    一篇笔记带你快速掌握面向对象的Javascript(纯手打)
  • 原文地址:https://www.cnblogs.com/dreagonm/p/10481052.html
Copyright © 2020-2023  润新知