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));
        }
    }
}
原文地址:https://www.cnblogs.com/suika/p/8413820.html