P3833 [SHOI2012]魔法树

题目背景

SHOI2012 D2T3

题目描述

Harry Potter 新学了一种魔法:可以让改变树上的果子个数。满心欢喜的他找到了一个巨大的果树,来试验他的新法术。

这棵果树共有N个节点,其中节点0是根节点,每个节点u的父亲记为fa[u],保证有fa[u] < u。初始时,这棵果树上的果子都被 Dumbledore 用魔法清除掉了,所以这个果树的每个节点上都没有果子(即0个果子)。

不幸的是,Harry 的法术学得不到位,只能对树上一段路径的节点上的果子个数统一增加一定的数量。也就是说,Harry 的魔法可以这样描述:

Add u v d

表示将点u和v之间的路径上的所有节点的果子个数都加上d。

接下来,为了方便检验 Harry 的魔法是否成功,你需要告诉他在释放魔法的过程中的一些有关果树的信息:

Query u

表示当前果树中,以点u为根的子树中,总共有多少个果子?

输入输出格式

输入格式:

 

第一行一个正整数N (1 ≤ N ≤ 100000),表示果树的节点总数,节点以0,1,…,N − 1标号,0一定代表根节点。

接下来N − 1行,每行两个整数a,b (0 ≤ a < b < N),表示a是b的父亲。

接下来是一个正整数Q(1 ≤ ? ≤ 100000),表示共有Q次操作。

后面跟着Q行,每行是以下两种中的一种:

  1. A u v d,表示将u到v的路径上的所有节点的果子数加上d;0 ≤ u,v <N,0 < d < 100000

  2. Q u,表示询问以u为根的子树中的总果子数,注意是包括u本身的。

 

输出格式:

 

对于所有的Query操作,依次输出询问的答案,每行一个。答案可能会超过2^32 ,但不会超过10^15 。

 

输入输出样例

输入样例#1: 复制
4
0 1
1 2
2 3
4
A 1 3 1
Q 0
Q 1
Q 2
输出样例#1: 复制
3
3
2


//裸树剖 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int N=1e5+5;

inline int read()
{
    char c=getchar();int num=0,f=1;
    for(;!isdigit(c);c=getchar())
        f=c=='-'?-1:f;
    for(;isdigit(c);c=getchar())
        num=num*10+c-'0';
    return num*f;
}

int n,q;
int head[N],num_edge;
struct Edge
{
    int v,nxt;
}edge[N];
struct NODE
{
    int son,fa;
    int s,t;
    int dep,siz;
    int top;
}node[N];
struct TREE
{
    TREE *lson,*rson;
    int l,r,mid,len;
    long long sum,lazy;
}tree[N<<2];

typedef TREE* Tree;
Tree now_node;

inline void add_edge(int u,int v)
{
    edge[++num_edge].v=v;
    edge[num_edge].nxt=head[u];
    head[u]=num_edge;
}

void dfs1(int u)
{
    node[u].siz=1;
    for(int i=head[u],v;i;i=edge[i].nxt)
    {
        v=edge[i].v;
        node[v].fa=u;
        node[v].dep=node[u].dep+1;
        dfs1(v);
        node[u].siz+=node[v].siz;
        if(node[u].son==0||node[v].siz>node[node[u].son].siz)
            node[u].son=v;
    }
}

int bound;
void dfs2(int u,int top)
{
    node[u].s=++bound;
    node[u].top=top;
    if(node[u].son)
    {
        dfs2(node[u].son,top);
        for(int i=head[u],v;i;i=edge[i].nxt)
        {
            v=edge[i].v;
            if(v==node[u].son)
                continue;
            dfs2(v,v);
        }
    }
    node[u].t=bound;
}

Tree Root;
void build(Tree &root,int l,int r)
{
    root=++now_node;
    root->l=l,root->r=r,root->mid=l+r>>1,root->len=r-l+1;
    if(l==r)
    {
//        root->lson=tree,
//        root->rson=tree;
        return;
    }
    build(root->lson,l,root->mid);
    build(root->rson,root->mid+1,r);
}

inline void pushdown(Tree root)
{
    if(!(root->lazy))
        return;
    root->lson->lazy+=root->lazy;
    root->rson->lazy+=root->lazy;
    root->lson->sum+=root->lson->len*root->lazy;
    root->rson->sum+=root->rson->len*root->lazy;
    root->lazy=0;
}

void modify(Tree root,int l,int r,int val)
{
    if(root->l==l&&root->r==r)
    {
        root->sum+=val*root->len;
        root->lazy+=val;
        return;
    }
    pushdown(root);
    if(r<=root->mid)
        modify(root->lson,l,r,val);
    else if(l>root->mid)
        modify(root->rson,l,r,val);
    else
    {
        modify(root->lson,l,root->mid,val);
        modify(root->rson,root->mid+1,r,val);
    }
    root->sum=root->lson->sum+root->rson->sum;
}

long long query(Tree root,int l,int r)
{
    if(root->l==l&&root->r==r)
        return root->sum;
    pushdown(root);
    if(r<=root->mid)
        return query(root->lson,l,r);
    else if(l>root->mid)
        return query(root->rson,l,r);
    else
        return query(root->lson,l,root->mid)+query(root->rson,root->mid+1,r);
}

void Modify(int x,int y,int val)
{
    int fx=node[x].top,fy=node[y].top;
    while(fx!=fy)
    {
        if(node[fx].dep>node[fy].dep)
        {
            modify(Root,node[fx].s,node[x].s,val);
            x=node[fx].fa,
            fx=node[x].top;
        }
        else
        {
            modify(Root,node[fy].s,node[y].s,val);
            y=node[fy].fa,
            fy=node[y].top;
        }
    }
    if(node[x].dep>node[y].dep)
        modify(Root,node[y].s,node[x].s,val);
    else
        modify(Root,node[x].s,node[y].s,val);
}

char s[5];
int main()
{
    now_node=tree;
    n=read();
    for(int i=1,a,b;i<n;++i)
    {
        a=read(),b=read();
        add_edge(a,b);
    }
    dfs1(0);
    dfs2(0,0);
    build(Root,1,n);
    q=read();
    for(int i=1,a,b,c;i<=q;++i)
    {
        scanf("%s",s);
        if(s[0]=='A')
        {
            a=read(),b=read(),c=read();
            Modify(a,b,c);
        }
        else
        {
            a=read();
            printf("%lld\n",query(Root,node[a].s,node[a].t));
        }
    }
    return 0;
}

 

posted @ 2018-05-20 21:45  whymhe  阅读(123)  评论(0编辑  收藏  举报