2021-04-19

题目:树上累加

#include <bits/stdc++.h>
#define N 101010
#define lson i<<1
#define rson i<<1|1
using namespace std;
const int mod=23333;
struct pp
{
    int x[2],lazy;
    int l,r;
}a[N<<3];//线段树
vector<int> v[N];//边
int w[N];//初始权重
int fa[N];//父节点
int has[N];//对应位置
int dfl[N],dfr[N],k;//对应子树的左端和右端
void dfs(int x)
{
    int i,n=v[x].size();
    int y;
    dfl[x]=++k;
    has[k]=x;
    for(i=0;i<n;i++)
    {
        y=v[x][i];
        if(fa[x]==y) continue;
        fa[y]=x;
        dfs(y);
    }
    dfr[x]=k;//
}
void add(int i,int x)//增加对应点权值
{
    int len=(a[i].r-a[i].l+1)%mod;
    a[i].lazy=(a[i].lazy+x)%mod;
    a[i].x[0]=(a[i].x[0]+2*a[i].x[1]*x+((len*x)%mod)*x%mod)%mod;
    a[i].x[1]=(a[i].x[1]+len*x)%mod;
}
void pushdown(int i)//向下更新
{
    if(a[i].lazy)
    {
        add(lson,a[i].lazy);
        add(rson,a[i].lazy);
        a[i].lazy=0;
    }
}
void pushup(int i)//向上更新
{
    a[i].x[0]=(a[lson].x[0]+a[rson].x[0])%mod;
    a[i].x[1]=(a[lson].x[1]+a[rson].x[1])%mod;
}
void build(int i,int l,int r)//建线段树
{
    a[i].l=l;
    a[i].r=r;
    if(l==r)
    {
        a[i].x[0]=w[has[l]]*w[has[l]]%mod;
        a[i].x[1]=w[has[l]];
        return ;
    }
    int mid=(l+r)>>1;
    build(lson,l,mid);
    build(rson,mid+1,r);
    pushup(i);
}
void updata(int i,int l,int r,int x)//更新
{
    if(l<=a[i].l&&a[i].r<=r)
    {
        add(i,x);
        return ;
    }
    if(r<a[i].l||a[i].r<l) return ;
    pushdown(i);
    updata(lson,l,r,x);
    updata(rson,l,r,x);
    pushup(i);
}
int qu(int i,int l,int r)//访问
{
    if(l<=a[i].l&&a[i].r<=r)return a[i].x[0];
    if(r<a[i].l||a[i].r<l) return 0;
    pushdown(i);
    return (qu(lson,l,r)+qu(rson,l,r))%mod;
}
int main()
{
    //freopen("in.txt","r",stdin);
    int i,n,q,s,t;
    scanf("%d%d",&n,&q);
    for(i=1;i<=n;i++)
    {
        scanf("%d",w+i);
        w[i]%=mod;
    }
    for(i=1;i<n;i++)//存图
    {
        scanf("%d%d",&s,&t);
        v[s].push_back(t);
        v[t].push_back(s);
    }
    dfs(1);//得dfs序
    build(1,1,n);//建线段树
    while(q--)
    {
        int x,y,z;
        scanf("%d",&z);
        if(z==1)
        {
            scanf("%d%d",&x,&y);
            updata(1,dfl[x],dfr[x],y%mod);

        }else
        {
            scanf("%d",&x);
            printf("%d\n",qu(1,dfl[x],dfr[x]));
        }
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值