haoi2015 树上操作

Posted lmjer

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了haoi2015 树上操作相关的知识,希望对你有一定的参考价值。

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

typedef  long long ll ;

struct my{
   ll next;
   ll v;
};

const int maxn=500000+20;
my tu[maxn];
ll d[maxn],size[maxn],fa[maxn],myson[maxn];
ll sum[maxn*8],lazy[maxn*8];
ll dfsn[maxn],last[maxn],top[maxn],pre[maxn];
ll dfn;
ll n,m;
ll adj[maxn];
ll w[maxn];
ll tot;

void myinsert(ll u,ll v){
     tu[++tot].v=v;
     tu[tot].next=adj[u];
     adj[u]=tot;
}

void dfs1(int u,int f){
     size[u]=1;
     for (int i=adj[u];i;i=tu[i].next){
        int v=tu[i].v;
        if(v==f) continue;
        d[v]=d[u]+1;fa[v]=u;
        dfs1(v,u);
        size[u]+=size[v];
        if(size[v]>size[myson[u]]) myson[u]=v;
     }
}

void dfs2(int u,int frist){
     dfsn[u]=++dfn;
     pre[dfn]=u;
     top[u]=frist;
     if(myson[u]) dfs2(myson[u],frist);
     for (int i=adj[u];i;i=tu[i].next){
         int v=tu[i].v;
         if(v==fa[u]||v==myson[u]) continue;
         dfs2(v,v);
     }
     last[u]=dfn;
}

void pushup(ll x){
    sum[x]=sum[x<<1]+sum[x<<1|1];
}

void build(ll l,ll r,ll rt){
     if(l==r){
        sum[rt]=w[pre[l]];
        return ;
     }
     int mid=(l+r)>>1;
     build(l,mid,rt<<1);
     build(mid+1,r,rt<<1|1);
     pushup(rt);
}

void pushdown(ll x,ll ln,ll rn){
     if(lazy[x]){
        sum[x<<1]+=lazy[x]*ln;
        sum[x<<1|1]+=lazy[x]*rn;
        lazy[x<<1]+=lazy[x];
        lazy[x<<1|1]+=lazy[x];
        lazy[x]=0;
     }
}

void change(ll l,ll r,ll rt,ll L,ll R,ll c){
     if(L<=l&&r<=R){
        sum[rt]+=c*(r-l+1);
        lazy[rt]+=c;
        return ;
     }
     ll mid=(l+r)>>1;
     pushdown(rt,mid-l+1,r-mid);
     if(L<=mid) change(l,mid,rt<<1,L,R,c);
     if(R>mid) change(mid+1,r,rt<<1|1,L,R,c);
     pushup(rt);
}

ll query(ll l,ll r,ll rt,ll L,ll R){
    if(L<=l&&r<=R){
        return sum[rt];
    }
    ll mid=(l+r)>>1;
    ll ans=0;
    pushdown(rt,mid-l+1,r-mid);
    if(L<=mid) ans+=query(l,mid,rt<<1,L,R);
    if(R>mid) ans+=query(mid+1,r,rt<<1|1,L,R);
    return ans;
}

ll getans(ll u){
    long long tu=top[u],ans=0;
    while (tu!=1){
        ans+=query(1,n,1,dfsn[tu],dfsn[u]);
        u=fa[tu];
        tu=top[u];
    }
    ans+=query(1,n,1,dfsn[1],dfsn[u]);
    return ans;
}

int main(){
    scanf("%lld%lld",&n,&m);
    for (ll i=1;i<=n;i++){
        scanf("%lld",&w[i]);
    }
    ll u,v;
    for (ll i=1;i<n;i++){
        scanf("%lld%lld",&u,&v);
        myinsert(u,v);
        myinsert(v,u);
    }
  d[1]=1;
  fa[1]=-1;
  dfs1(1,-1);
  dfs2(1,1);
  n;
  build(1,n,1);
   ll biao;
   ll x;
   ll a;
   while(m--){
     scanf("%lld",&biao);
     if(biao==1) {
          scanf("%lld%lld",&x,&a);
          change(1,n,1,dfsn[x],dfsn[x],a);
     }
     if(biao==2){
        scanf("%lld%lld",&x,&a);
        change(1,n,1,dfsn[x],last[x],a);
     }
     if(biao==3) {
        scanf("%lld",&x);
        printf("%lld\n",getans(x));
     }
   }
return 0;
}

以上是关于haoi2015 树上操作的主要内容,如果未能解决你的问题,请参考以下文章

[BZOJ4034][HAOI2015]树上操作

BZOJ 4034 HAOI2015 树上操作

[HAOI2015]树上操作 -树链剖分

cogs 1963. [HAOI 2015] 树上操作 树链剖分+线段树

[HAOI2015]树上操作

HAOI2015 树上操作