返回顶部

P3178 [HAOI2015]树上操作

题目传送锚点

这是一道树链剖分的简化板子题:

一定要记得开long long!!!

所以我直接:#define int long long

树链剖分详见:传送锚点

Code:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+5;
int n,m,tot,num;
int fi[N],ne[N*2],to[N*2];
int fa[N],si[N],son[N],d[N];
int id[N],top[N];
int a[N],w[N],la[N*4];
struct xiao
{
    int l,r,w;
}tr[N*4];

void pu(int x)
{
    if(la[x])
    {
        tr[x<<1].w+=la[x]*(tr[x<<1].r-tr[x<<1].l+1);
        tr[x<<1|1].w+=la[x]*(tr[x<<1|1].r-tr[x<<1|1].l+1);
        la[x<<1]+=la[x];
        la[x<<1|1]+=la[x];
        la[x]=0;
    }
}

void add(int x,int y)
{
    ne[++tot]=fi[x];
    fi[x]=tot;
    to[tot]=y;
}

void dfs1(int x,int y)
{
    d[x]=d[y]+1;
    si[x]=1;
    for(int i=fi[x];i;i=ne[i])
    {
        int v=to[i];
        if(v==y) continue;
        dfs1(v,x);
        fa[v]=x,si[x]+=si[v];
        if(si[v]>si[son[x]]) son[x]=v;
    }
}

void dfs2(int x,int y)
{
    top[x]=y;
    id[x]=++num;
    w[num]=a[x];
    if(son[x]) dfs2(son[x],y);
    for(int i=fi[x];i;i=ne[i])
    {
        int v=to[i];
        if(v==fa[x]||v==son[x]) continue;
        dfs2(v,v);
    }
}

void bu(int x,int l,int r)
{
    tr[x].l=l,tr[x].r=r;
    if(l==r)
    {
        tr[x].w=w[l];
        return;
    }
    int mid=(l+r)>>1;
    bu(x<<1,l,mid),bu(x<<1|1,mid+1,r);
    tr[x].w=tr[x<<1].w+tr[x<<1|1].w;
}

void u(int x,int l,int r,int k)
{
    pu(x);
    if(tr[x].l>=l&&tr[x].r<=r)
    {
        tr[x].w+=k*(tr[x].r-tr[x].l+1);
        la[x]+=k;
        return;
    }
    int mid=(tr[x].l+tr[x].r)>>1;
    if(l<=mid) u(x<<1,l,r,k);
    if(r>mid) u(x<<1|1,l,r,k);
    tr[x].w=tr[x<<1].w+tr[x<<1|1].w;
}

void us(int x,int k)
{
    u(1,id[x],id[x]+si[x]-1,k);
}

int q(int x,int l,int r)
{
    pu(x);
    if(tr[x].l>=l&&tr[x].r<=r)
        return tr[x].w;
    int mid=(tr[x].l+tr[x].r)>>1;
    int s=0;
    if(l<=mid) s+=q(x<<1,l,r);
    if(r>mid) s+=q(x<<1|1,l,r);
    return s;
}

int qu(int x)
{
    int s=0;
    while(top[x]!=top[1])
        s+=q(1,id[top[x]],id[x]),x=fa[top[x]];
    s+=q(1,1,id[x]);
    return s;
}

signed main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    for(int i=1;i<n;i++)
    {
        int x,y;
        cin>>x>>y;
        add(x,y),add(y,x); 
    }
    dfs1(1,0);
    dfs2(1,1);
    bu(1,1,n);
    while(m--)
    {
        int op,x,y;
        cin>>op;
        if(op==1)
        {
            cin>>x>>y;
            u(1,id[x],id[x],y);
        }
        if(op==2)
        {
            cin>>x>>y;
            us(x,y); 
        }
        if(op==3)
        {
            cin>>x;
            cout<<qu(x)<<'\n';
        }
    }
}

 

posted @ 2022-10-10 11:07  光暗之影x  阅读(6)  评论(0)    收藏  举报