HAOI2015 树上操作

题目描述

题解:

线段树维护dfs序。

貌似是裸题。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 100050
#define ll long long
inline int rd()
{
    int f=1,c=0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();}
    return f*c;
}
int n,m,hed[N],cnt=0;
struct EG
{
    int to,nxt;
}e[2*N];
void ae(int f,int t)
{
    e[++cnt].to = t;
    e[cnt].nxt = hed[f];
    hed[f] = cnt;
}
int a[N];
int tin[N],tout[N],tim,k[N<<1],K[N<<1];
void dfs(int u,int fa)
{
    tin[u] = ++tim;k[tim]=1;K[tim]=a[u];
    for(int j=hed[u];j;j=e[j].nxt)
    {
        int to = e[j].to;
        if(to==fa)continue;
        dfs(to,u);
    }
    tout[u]=++tim;k[tim]=-1;K[tim]=-a[u];
}
struct segtree
{
    ll v[N<<3],tag[N<<3],siz[N<<3];
    void add(int u,ll d)
    {
        tag[u]+=d;
        v[u]+=d*siz[u];
    }
    void pushdown(int u)
    {
        if(tag[u])
        {
            add(u<<1,tag[u]);
            add(u<<1|1,tag[u]);
            tag[u]=0;
        }
    }
    void update(int u)
    {
        v[u] = v[u<<1]+v[u<<1|1]+siz[u]*tag[u];
    }
    void build(int l,int r,int u)
    {
        if(l==r)
        {
            siz[u]=k[l];
            v[u] = K[l];
            tag[u]=0;
            return ;
        }
        int mid = (l+r)>>1;
        build(l,mid,u<<1);
        build(mid+1,r,u<<1|1);
        siz[u] = siz[u<<1]+siz[u<<1|1];
        update(u);
    }
    void insert(int l,int r,int u,int ql,int qr,ll d)
    {
        if(l==ql&&r==qr)
        {
            add(u,d);
            return ;
        }
        pushdown(u);
        int mid = (l+r)>>1;
        if(qr<=mid)insert(l,mid,u<<1,ql,qr,d);
        else if(ql>mid)insert(mid+1,r,u<<1|1,ql,qr,d);
        else insert(l,mid,u<<1,ql,mid,d),insert(mid+1,r,u<<1|1,mid+1,qr,d);
        update(u);
    }
    ll query(int l,int r,int u,int ql,int qr)
    {
        if(l==ql&&r==qr)return v[u];
        pushdown(u);
        int mid = (l+r)>>1;
        if(qr<=mid)return query(l,mid,u<<1,ql,qr);
        else if(ql>mid)return query(mid+1,r,u<<1|1,ql,qr);
        else return query(l,mid,u<<1,ql,mid)+query(mid+1,r,u<<1|1,mid+1,qr);
    }
}tr;
int main()
{
    n=rd(),m=rd();
    for(int i=1;i<=n;i++)
    {
        a[i]=rd();
    }
    for(int f,t,i=1;i<n;i++)
    {
        f=rd(),t=rd();
        ae(f,t),ae(t,f);
    }
    dfs(1,0);
    tr.build(1,tim,1);
    for(int typ,x,y,i=1;i<=m;i++)
    {
        typ=rd();
        if(typ==1)
        {
            x=rd(),y=rd();
            tr.insert(1,tim,1,tin[x],tin[x],y);
            tr.insert(1,tim,1,tout[x],tout[x],y);
        }else if(typ==2)
        {
            x=rd(),y=rd();
            tr.insert(1,tim,1,tin[x],tout[x],y);
        }else if(typ==3)
        {
            x=rd();
            ll ans = tr.query(1,tim,1,1,tin[x]);
            printf("%lld\n",ans);
        }else break;
    }
    return 0;
}

 

posted @ 2018-12-21 13:03  LiGuanlin  阅读(157)  评论(0编辑  收藏  举报