P3833 [SHOI2012]魔法树

P3833 [SHOI2012]魔法树

丢人现场:线段树传标记打挂

以后LZT一定+=!

正经:这是一道裸的树剖

没有可说的

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=100005;
#define il inline
typedef long long ll;
int n,m;
int fa[N];
int dep[N];
int size[N]={0};
int son[N]={0};
int dfn[N];
int indexy=0;
int rk[N];
int top[N];
int hed[N],tal[N<<1],nxt[N<<1],cnt=0;
struct Sugment_Tree{
    ll t[N<<2];
    ll LZT[N<<2];
    #define mid (l+r)/2
    il void push_up(int num){
        t[num]=t[num<<1]+t[num<<1|1];
    } 
    Sugment_Tree(){memset(LZT,0,sizeof(LZT));}
    il void push_down(int l,int r,int num){
        if(LZT[num]==0) return;
        LZT[num<<1]+=LZT[num];
        LZT[num<<1|1]+=LZT[num];
        t[num<<1]+=(ll)(mid-l+1)*LZT[num];
        t[num<<1|1]+=(ll)(r-(mid+1)+1)*LZT[num];
        LZT[num]=0;
    }
    il void build(int l,int r,int num){
        if(l==r){
            t[num]=0;
            LZT[num]=0;
            return;
        }
        build(l,mid,num<<1);build(mid+1,r,num<<1|1);
        push_up(num);
    }
    il void upt(int l,int r,int num,int L,int R,ll SUM){
        //cout<<l<<"&@*& "<<r <<" "<<num<<" "<<L<<" "<<R<<" "<<SUM<<endl;
        if(l>R||r<L) return;
        if(l>=L&&r<=R){
            t[num]+=(ll)(r-l+1)*SUM;
            LZT[num]+=SUM;
            return;
        }
        push_down(l,r,num);
        upt(l,mid,num<<1,L,R,SUM);
        upt(mid+1,r,num<<1|1,L,R,SUM);
        push_up(num);
    }
    il ll ask(int l,int r,int num,int L,int R){
        if(l>R||r<L) return 0ll;
        if(l>=L&&r<=R){
            return t[num];
        }
        push_down(l,r,num);
        return ask(l,mid,num<<1,L,R)+ask(mid+1,r,num<<1|1,L,R);
    }
}T;
il void cgn(int x,int y,ll SUM){
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
    //    cout<<dfn[top[x]]<<" &@$&$ "<<dfn[x]<<endl;
        T.upt(1,n,1,dfn[top[x]],dfn[x],SUM);
        x=fa[top[x]];
    }
    if(dep[x]<dep[y]) swap(x,y);
    //cout<<dfn[y]<<" &@$&$ "<<dfn[x]<<endl;
    T.upt(1,n,1,dfn[y],dfn[x],SUM);
    
}
il void addege(int x,int y){
    cnt++;
    tal[cnt]=y;
    nxt[cnt]=hed[x];
    hed[x]=cnt;
}
il void dfs1(int u){
    size[u]=1;
    for(int i=hed[u];i;i=nxt[i]){
        int v=tal[i];
        if(v==fa[u]) continue;
        dep[v]=dep[u]+1;
        dfs1(v);
        size[u]+=size[v];
        if(size[v]>size[son[u]]) son[u]=v;
    }
}
il void dfs2(int u,int tp){
    indexy++;
    dfn[u]=indexy;
    rk[dfn[u]]=u;
    top[u]=tp;
    if(!son[u]) return;
    dfs2(son[u],tp);
    for(int i=hed[u];i;i=nxt[i]){
        int v=tal[i];
        if(v==fa[u]||v==son[u]) continue;
        dfs2(v,v);
    }
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<n;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        x++,y++;
        fa[y]=x;
        addege(x,y);
        addege(y,x);
    }
    dep[1]=1;
    dfs1(1);//两个dfs预处理 
    dfs2(1,1);
    //for(int i=1;i<=n;i++) cout<<son[i]<<" ";
//    cout<<endl;
    T.build(1,n,1);
    scanf("%d",&m);
    while(m--){
        char c[10];
        scanf("%s",c);
        
        if(c[0]=='A'){
            int x,y;
            ll val;
            scanf("%d%d%lld",&x,&y,&val);
            x++,y++;
            cgn(x,y,val);
        }
        else{
            int u;
            scanf("%d",&u);
            u++;
            //cout<<dfn[u]<<" &*%&&$* "<<dfn[u]+size[u]-1<<endl;
            printf("%lld\n",T.ask(1,n,1,dfn[u],dfn[u]+size[u]-1));
        }
    }
    return 0;
} 

 

posted @ 2019-10-04 11:22  QYJ060604  阅读(113)  评论(0编辑  收藏  举报