[BZOJ 4034] 树上操作

Link:

BZOJ 4034 传送门

Solution:

树剖模板题……

Code:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
#define mid ((l+r)>>1)
#define lc k<<1,l,mid
#define rc k<<1|1,mid+1,r
const int MAXN=1e5+10;
struct edge{int to,nxt;}e[MAXN<<2];
ll seg[MAXN<<2],tag[MAXN<<2];
int n,m,x,y,head[MAXN],dep[MAXN],dat[MAXN],sz[MAXN],top[MAXN],pos[MAXN],f[MAXN],cnt,tot;

void add_edge(int from,int to)
{e[++tot].nxt=head[from];e[tot].to=to;head[from]=tot;}

void dfs1(int x)
{
    sz[x]=1;
    for(int i=head[x];i;i=e[i].nxt)
    {
        if(e[i].to==f[x]) continue;
        f[e[i].to]=x;dep[e[i].to]=dep[x]+1;
        dfs1(e[i].to);sz[x]+=sz[e[i].to]; 
    }
}

void dfs2(int x,int up)
{
    int bs=0;top[x]=up;pos[x]=++cnt;
    for(int i=head[x];i;i=e[i].nxt)
        if(e[i].to!=f[x]&&sz[e[i].to]>sz[bs]) bs=e[i].to;
    if(!bs) return;
    dfs2(bs,up);
    for(int i=head[x];i;i=e[i].nxt)
        if(e[i].to!=f[x]&&e[i].to!=bs) dfs2(e[i].to,e[i].to);
}

void pushdown(int k,int l,int r)
{
    if(!tag[k]) return;
    tag[k<<1]+=tag[k];tag[k<<1|1]+=tag[k];
    seg[k<<1]+=tag[k]*(mid-l+1);
    seg[k<<1|1]+=tag[k]*(r-mid);
    tag[k]=0;
}

void Update(int a,int b,int x,int k,int l,int r)
{
    if(a<=l&&r<=b)
    {seg[k]+=1ll*x*(r-l+1);tag[k]+=x;return;}
    
    pushdown(k,l,r);
    if(a<=mid) Update(a,b,x,lc);
    if(b>mid) Update(a,b,x,rc);
    seg[k]=seg[k<<1]+seg[k<<1|1];
}

ll Query(int a,int b,int k,int l,int r)
{
    if(a<=l&&r<=b) return seg[k];
    ll ret=0;pushdown(k,l,r);
    if(a<=mid) ret+=Query(a,b,lc);
    if(b>mid) ret+=Query(a,b,rc);
    return ret;
}

ll solve_query(int a,int b)
{
    ll ret=0;
    while(top[a]!=top[b])
    {
        if(dep[top[a]]<dep[top[b]]) swap(a,b);
        ret+=Query(pos[top[a]],pos[a],1,1,n);
        a=f[top[a]];
    }
    if(pos[a]>pos[b]) swap(a,b);
    ret+=Query(pos[a],pos[b],1,1,n);
    return ret;
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&dat[i]);
    for(int i=1;i<n;i++)
        scanf("%d%d",&x,&y),add_edge(x,y),add_edge(y,x);
    dfs1(1);dfs2(1,1);
    for(int i=1;i<=n;i++) Update(pos[i],pos[i],dat[i],1,1,n);
    
    while(m--)
    {
        int op,x,a;scanf("%d%d",&op,&x);
        if(op!=3) scanf("%d",&a);
        if(op==1) Update(pos[x],pos[x],a,1,1,n);
        else if(op==2) Update(pos[x],pos[x]+sz[x]-1,a,1,1,n); 
        else printf("%lld\n",solve_query(1,x));
    }
    return 0;
}

 

posted @ 2018-07-12 08:40  NewErA  阅读(123)  评论(0编辑  收藏  举报