zoukankan      html  css  js  c++  java
  • 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
    ",query(Root,node[a].s,node[a].t));
            }
        }
        return 0;
    }
  • 相关阅读:
    zoj 3279 线段树 OR 树状数组
    fzu 1962 树状数组 OR 线段树
    hdu 5057 块状链表
    hdu3487 Play with Chain
    bzoj 1588营业额统计(HNOI 2002)
    poj2823 Sliding Window
    poj2828 Buy Tickets
    poj2395 Out of Hay
    poj3667 Hotel
    poj1703 Lost Cows
  • 原文地址:https://www.cnblogs.com/lovewhy/p/9064757.html
Copyright © 2011-2022 走看看