P3833 [SHOI2012]魔法树

Posted qyj060604

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
 

 

以上是关于P3833 [SHOI2012]魔法树的主要内容,如果未能解决你的问题,请参考以下文章

P3833 [SHOI2012]魔法树

[SHOI 2012] 魔法树

洛谷 3833 SHOI 2012 魔法树

[SHOI2012]魔法树

luogu3833SHOI2012魔法树

[SHOI2012]随机树