洛谷P3178 [HAOI2015]树上操作 (树链剖分)

题目链接:

https://www.luogu.com.cn/problem/P3178

思路:

树剖板子

代码:

#include <bits/stdc++.h>
#define ls node<<1
#define rs node<<1|1
using namespace std;
typedef long long ll;
const int MAXN=2e5+5;
ll n,m;
ll head[MAXN],tot;
struct node
{
    ll to,nxt;
}e[MAXN<<1];
void add(ll x,ll y)
{
    e[tot].to=y;e[tot].nxt=head[x];head[x]=tot++;
}
void add_edge(ll x,ll y){add(x,y);add(y,x);}
ll dep[MAXN],f[MAXN],sz[MAXN],son[MAXN];
void dfs(int u,int fa)
{
    dep[u]=dep[fa]+1;sz[u]=1;f[u]=fa;
    for(int i=head[u];~i;i=e[i].nxt)
    {
        ll v=e[i].to;
        if(v!=fa)
        {
            dfs(v,u);
            sz[u]+=sz[v];
            if(sz[v]>sz[son[u]])
                son[u]=v;
        }
    }
}
ll top[MAXN],id[MAXN],val[MAXN],a[MAXN],cnt;
void dfs2(ll u,ll t)
{
    top[u]=t;id[u]=++cnt;a[cnt]=val[u];
    if(son[u])
        dfs2(son[u],t);
    for(int i=head[u];~i;i=e[i].nxt)
    {
        ll v=e[i].to;
        if(v!=f[u]&&v!=son[u])
            dfs2(v,v);
    }
}
ll tree[MAXN<<2],lazy[MAXN<<2];
void push_up(ll node)
{
    tree[node]=tree[ls]+tree[rs];
}
void build(ll node,ll l,ll r)
{
    if(l==r){tree[node]=a[l];return;}
    ll mid=(l+r)>>1;
    build(ls,l,mid);build(rs,mid+1,r);
    push_up(node);
}
void push_down(ll node,ll l,ll r,ll mid)
{
    if(lazy[node])
    {
        lazy[ls]+=lazy[node];lazy[rs]+=lazy[node];
        tree[ls]+=lazy[node]*(mid-l+1);tree[rs]+=lazy[node]*(r-mid);
        lazy[node]=0;
    }
}
void update(ll node,ll l,ll r,ll x,ll y,ll k)
{
    if(l>=x&&r<=y)
    {
        lazy[node]+=k;tree[node]+=(r-l+1)*k;return;
    }
    ll mid=(l+r)>>1;
    push_down(node,l,r,mid);
    if(x<=mid)
        update(ls,l,mid,x,y,k);
    if(y>mid)
        update(rs,mid+1,r,x,y,k);
    push_up(node);
}
ll query(ll node,ll l,ll r,ll x,ll y)
{
    if(l>=x&&r<=y)
    {
        //cout<<tree[node]<<endl;
        return tree[node];
    }
    ll mid=(l+r)>>1;
    push_down(node,l,r,mid);
    ll ans=0;
    if(x<=mid)
        ans+=query(ls,l,mid,x,y);
    if(y>mid)
        ans+=query(rs,mid+1,r,x,y);
    return ans;
}
ll tree_sum(ll x,ll y)
{
    ll fx=top[x],fy=top[y];ll ans=0;
    while(fx!=fy)
    {
        if(dep[fx]<dep[fy])swap(x,y),swap(fx,fy);
        ans+=query(1,1,n,id[fx],id[x]);

        x=f[fx];fx=top[x];
    }
    if(id[x]>id[y])swap(x,y);
    //cout<<id[x]<<" "<<id[y]<<endl;
    ans+=query(1,1,n,id[x],id[y]);
    return ans;
}
int main()
{
    memset(head,-1,sizeof(head));
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&val[i]);
    }
    for(int i=1;i<n;i++)
    {
        ll x,y;scanf("%lld%lld",&x,&y);
        add_edge(x,y);
    }
    dfs(1,0);dfs2(1,1);build(1,1,n);
    while(m--)
    {
        int op;scanf("%d",&op);
        ll x,y;
        if(op==1)
        {
            scanf("%lld%lld",&x,&y);
            update(1,1,n,id[x],id[x],y);
        }
        if(op==2)
        {
            scanf("%lld%lld",&x,&y);
            update(1,1,n,id[x],id[x]+sz[x]-1,y);
        }
        if(op==3)
        {
            scanf("%lld",&x);
            printf("%lld\n",tree_sum(1,x));
        }
    }
    return 0;
}

 

posted @ 2020-03-29 19:58  grass_lin  阅读(105)  评论(0编辑  收藏  举报