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\n",query(a));
        }
    }
    return 0;
}
posted @ 2019-03-06 07:41  dreagonm  阅读(282)  评论(0编辑  收藏  举报