• B20J_2836_魔法树_树链剖分+线段树


    B20J_2836_魔法树_树链剖分+线段树

    题意:

    果树共有N个节点,其中节点0是根节点,每个节点u的父亲记为fa[u]。初始时,这个果树的每个节点上都没有果子(即0个果子)。

    Add u v d

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

    Query u

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

    分析:树链剖分+线段树模板题。记录一下x结点的子树中最后一次出现的位置即可。

    代码:

    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define N 100010
    #define lson pos<<1
    #define rson pos<<1|1
    #define LL long long
    int head[N],to[N<<1],nxt[N<<1],cnt,n,tot,m;
    int dep[N],siz[N],fa[N],son[N],idx[N],top[N],sec[N];
    LL t[N<<2],lz[N<<2];
    char ch[10];
    inline void read(int &x)
    {
        int f=1;x=0;char s=getchar();
        while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
        while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+s-'0';s=getchar();}
        x*=f;
    }
    inline void add(int u,int v)
    {
        to[++cnt]=v;
        nxt[cnt]=head[u];
        head[u]=cnt;    
    }
    inline void dfs1(int x,int y)
    {
        dep[x]=dep[y]+1;
        fa[x]=y;
        siz[x]=1;
        for(int i=head[x];i;i=nxt[i])
        {
            if(to[i]!=y)
            {
                dfs1(to[i],x);
                siz[to[i]]+=siz[x];
                if(siz[to[i]]>siz[son[x]])
                {
                    son[x]=to[i];
                }
            }
        }
    }
    inline void dfs2(int x,int t)
    {
        top[x]=t;
        idx[x]=++tot;
        if(son[x])dfs2(son[x],t);
        for(int i=head[x];i;i=nxt[i])
        {
            if(to[i]!=fa[x]&&to[i]!=son[x])
            {
                dfs2(to[i],to[i]);
            }
        }
        sec[x]=tot;
    }
    inline void pud(int l,int r,int pos,int c)
    {
        t[pos]+=(r-l+1)*c;
        lz[pos]+=c;    
    }
    inline void up(int l,int r,int x,int y,int z,int pos)
    {
        if(x<=l&&y>=r)
        {
            t[pos]+=(r-l+1)*z;
            lz[pos]+=z;
            return ;
        }
        int mid=l+r>>1;
        if(lz[pos])
        {
            pud(l,mid,lson,lz[pos]);
            pud(mid+1,r,rson,lz[pos]);
            lz[pos]=0;    
        }
        if(x<=mid)up(l,mid,x,y,z,lson);
        if(y>mid)up(mid+1,r,x,y,z,rson);
        t[pos]=t[lson]+t[rson];
    }
    inline LL query(int l,int r,int x,int y,int pos)
    {
        if(x<=l&&y>=r)
        {
            return t[pos];
        }
        int mid=l+r>>1;
        if(lz[pos])
        {
            pud(l,mid,lson,lz[pos]);
            pud(mid+1,r,rson,lz[pos]);
            lz[pos]=0;    
        }
        LL re=0;
        if(x<=mid)re+=query(l,mid,x,y,lson);
        if(y>mid)re+=query(mid+1,r,x,y,rson);
        return re;
    }
    int main()
    {
        read(n);
        register int x,y,i,z;
        for(i=1;i<n;++i)
        {
            read(x),read(y);
            add(x+1,y+1);
            add(y+1,x+1);    
        }
        dfs1(1,0);
        dfs2(1,1);
        read(m);
        while(m--)
        {
            scanf("%s",ch);
            if(ch[0]=='A')
            {
                read(x),read(y),read(z);
                x++,y++;
                while(top[x]!=top[y])
                {
                    if(dep[top[x]]>dep[top[y]])swap(x,y);
                    up(1,n,idx[top[y]],idx[y],z,1);
                    y=fa[top[y]];    
                }
                if(dep[x]<dep[y])swap(x,y);
                up(1,n,idx[y],idx[x],z,1);
            }
            else
            {
                read(x);
                x++;
                printf("%lld
    ",query(1,n,idx[x],sec[x],1));
            }
        }
    }
    
  • 相关阅读:
    Metabase研究 开源的数据报表
    Redis配置不当致使root被提权漏洞
    一个程序员被骗去养猪
    调度器简介,以及Linux的调度策略
    Linux的内存分页管理
    在地铁11号线上写书
    为什么说“概率”带来一场现代革命?
    快速学习Bash
    用树莓派玩转蓝牙
    树莓派的GPIO编程
  • 原文地址:https://www.cnblogs.com/suika/p/8413820.html
Copyright © 2020-2023  润新知