带注释,样例已过求调
查看原帖
带注释,样例已过求调
1159333
A_Little_BadBoy楼主2024/6/23 14:38
#include <bits/stdc++.h>
using namespace std;
#define int long long
//P3178

const int N=2e5+5;
struct node
{
    int val;
    int lazy;
}seg[N<<2];
int n,m,a,b,cnt,type;
vector<int>all[N];
int fa[N],siz[N],top[N],son[N],dep[N],init[N];
int tag[N];//重新确定编号

inline void dfs1(int m1)
{
    siz[m1]=1;
    for(int i:all[m1])
    {
        if(i==fa[m1])continue;
        fa[i]=m1;
        dep[i]=dep[m1]+1;
        dfs1(i);
        siz[m1]+=siz[i];
        if(siz[i]>siz[son[m1]])son[m1]=i;
    }
}

inline void dfs2(int pos,int gtop)
{
    tag[pos]=++cnt;//在dfs2时赋新值可以保证连续性
    top[pos]=gtop;
    if(son[pos])dfs2(son[pos],gtop);
    for(int i:all[pos])
    {
        if(i==son[pos]||i==fa[pos])continue;
        dfs2(i,i);
    }
}

inline void Pushdown(int root,int len,int ren)
{
    int tmp=seg[root].lazy;
    seg[root<<1].val+=tmp*len;
    seg[root<<1|1].val+=tmp*ren;
    seg[root<<1].lazy+=tmp;
    seg[root<<1|1].lazy+=tmp;
    seg[root].lazy=0;
}

inline void Build(int L,int R,int root)
{
    if(L==R)
    {
        seg[root].val=init[tag[L]];
        return;
    }

    int mid=L+R>>1;
    Build(L,mid,root<<1);
    Build(mid+1,R,root<<1|1);
    seg[root].val=seg[root<<1].val+seg[root<<1|1].val;
}

inline void Modify(int l,int r,int L,int R,int root,int c)
{
    if(L>r||R<l)return;
    if(L>=l&&R<=r)
    {
        seg[root].val+=(R-L+1)*c;
        seg[root].lazy+=c;
        return;
    }

    int mid=L+R>>1;
    Pushdown(root,mid-L+1,R-mid);
    Modify(l,r,L,mid,root<<1,c);
    Modify(l,r,mid+1,R,root<<1|1,c);
    seg[root].val=seg[root<<1].val+seg[root<<1|1].val;
}

inline int Query(int l,int r,int L,int R,int root)
{
    if(L>r||R<l)return 0;
    if(L>=l&&R<=r)return seg[root].val;

    int mid=L+R>>1;
    Pushdown(root,mid-L+1,R-mid);
    return Query(l,r,L,mid,root<<1)+Query(l,r,mid+1,R,root<<1|1);
}

signed main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;i++)cin>>init[i];//节点初始值
    for(int i=1;i<=n-1;i++)
    {
        cin>>a>>b;
        all[a].push_back(b);
        all[b].push_back(a);
    }
    //该题中,以节点1为根
    dfs1(1);
    dfs2(1,1);
    Build(1,n,1);
    while(m--)
    {
        cin>>type;
        if(type==1)//把节点a的点权增加b
        {
            cin>>a>>b;
            Modify(tag[a],tag[a],1,n,1,b);//单点修改
        }
        else if(type==2)//把以节点a为根的子树所有点的点权增加b
        {
            cin>>a>>b;
            Modify(tag[a],tag[a]+siz[tag[a]]-1,1,n,1,b);//子树修改,区间为tag[a]~tag[a]+siz[tag[a]]-1
        }
        else//查询从a到1路径中所有点的点权和
        {
            //为了使这段代码具有通用性,这里写的是从a到b的路径权值和
            cin>>a;b=1;
            int ans=0;
            while(top[a]!=top[b])
            {
                if(dep[top[a]]<dep[top[b]])swap(a,b);
                ans+=Query(tag[top[a]],tag[a],1,n,1);
                a=fa[top[a]];
            }
            if(dep[a]<dep[b])swap(a,b);
            ans+=Query(tag[b],tag[a],1,n,1);
            cout<<ans<<'\n';
        }
    }
    return 0;
}

2024/6/23 14:38
加载中...