洛谷P3833 [SHOI2012]魔法树

树剖模板+1 记得开long long

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define maxn 100010

using namespace std;

struct node
{
    int ed,nxt;
};
node edge[maxn<<1];
int n,m,first[maxn],cnt;
int fa[maxn],siz[maxn],son[maxn],dep[maxn];
int rnk[maxn],seg[maxn],top[maxn],rnk_cnt;
long long tree[maxn<<2],tag[maxn<<2],ans,tot;

inline void add_edge(int s,int e)
{
    ++cnt;
    edge[cnt].ed=e;
    edge[cnt].nxt=first[s];
    first[s]=cnt;
    return;
}

inline void dfs_1(int now,int pre)
{
    dep[now]=dep[pre]+1; fa[now]=pre; siz[now]=1;
    for(register int i=first[now];i;i=edge[i].nxt)
    {
        int e=edge[i].ed;
        if(e==fa[now]) continue;
        dfs_1(e,now);
        siz[now]+=siz[e];
        if(son[now]==-1||siz[e]>siz[son[now]]) son[now]=e;
    }
    return;
}

inline void dfs_2(int now,int heavy_fa)
{
    top[now]=heavy_fa;
    ++rnk_cnt;
    rnk[now]=rnk_cnt; seg[rnk_cnt]=now; 
    if(son[now]==-1) return;
    dfs_2(son[now],heavy_fa);
    for(register int i=first[now];i;i=edge[i].nxt)
    {
        int e=edge[i].ed;
        if(e!=fa[now]&&e!=son[now]) dfs_2(e,e);
    }
    return;
}

inline void push_down(int k,int l,int r)
{
    int mid=(l+r)>>1,son=k<<1;
    tree[son]=(tree[son]+(mid-l+1)*tag[k]); tag[son]=(tag[son]+tag[k]);
    tree[son|1]=(tree[son|1]+(r-mid)*tag[k]); tag[son|1]=(tag[son|1]+tag[k]);
    tag[k]=0;
    return;
}

inline void modify(int k,int l,int r,int x,int y,int v)
{
    if(r<x||l>y) return;
    if(x<=l&&r<=y)
    {
        tree[k]=(tree[k]+v*(r-l+1));
        tag[k]=(tag[k]+v);
        return;
    }
    if(tag[k]) push_down(k,l,r);
    int mid=(l+r)>>1,son=k<<1;
    modify(son,l,mid,x,y,v); modify(son|1,mid+1,r,x,y,v);
    tree[k]=(tree[son]+tree[son|1]);
    return;
}

inline void modify_tree(int x,int y,int v)
{
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        modify(1,1,n,rnk[top[x]],rnk[x],v);
        x=fa[top[x]];
    }
    modify(1,1,n,min(rnk[x],rnk[y]),max(rnk[x],rnk[y]),v);
    return;
}

inline void get_sum(int k,int l,int r,int x,int y)
{
    if(r<x||l>y) return;
    if(x<=l&&r<=y)
    {
        tot+=tree[k];
        return;
    }
    if(tag[k]) push_down(k,l,r);
    int mid=(l+r)>>1,son=k<<1;
    get_sum(son,l,mid,x,y); get_sum(son|1,mid+1,r,x,y);
    tree[k]=tree[son]+tree[son|1];
    return;
}

int main()
{
    scanf("%d",&n);
    for(register int i=1;i<=n-1;++i)
    {
        int s,e;
        scanf("%d%d",&s,&e);
        add_edge(s+1,e+1);
        add_edge(e+1,s+1);
    }
    memset(son,-1,sizeof(son));
    dfs_1(1,0);
    dfs_2(1,1);
    scanf("%d",&m);
    for(register int i=1;i<=m;++i)
    {
        char opt;
        cin>>opt;
        if(opt=='A')
        {
            int x,y,v;
            scanf("%d%d%d",&x,&y,&v);
            modify_tree(x+1,y+1,v);
        }
        else
        {
            tot=0;
            int x;
            scanf("%d",&x);
            x++;
            get_sum(1,1,n,rnk[x],rnk[x]+siz[x]-1);
            printf("%lld
",tot);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/Hoyoak/p/11817254.html