返回顶部

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 @   光暗之影x  阅读(2)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示