题目链接
解题报告:
将树转化成dfs序,对于任意节点及其子树总是一段连续的区间,那么转化成区间问题。
( ai + b ) ^2 = ai*ai + 2*ai*b + b*b 很明显线段树维护即可。
#define first f
#define second s
#define ll long long
#define mp make_pair
#define pb push_back
#define pf push_front
#define lb lower_bound
#define ub upper_bound
#include <bits/stdc++.h>
#define pii pair<int,int>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn=1e5+5;
const int inf=0x3f3f3f3f;
const int MOD=23333;
const double PI=acos(-1);
const double e=2.718281828459;
pii edge[maxn<<1];
int laz1[maxn<<2],sum1[maxn<<2],sum2[maxn<<2];
int in[maxn],out[maxn],head[maxn],a[maxn],dfn[maxn];
int cnt=0,knt=0;
void add(int from,int to)
{
edge[++cnt].s=head[from];
edge[cnt].f=to;
head[from]=cnt;
}
void dfs(int now,int pre)
{
in[now]=++knt;
dfn[knt]=now;
for(int i=head[now];~i;i=edge[i].s){
int to=edge[i].f;
if(to==pre){continue;}
dfs(to,now);
}
out[now]=knt;
}
void pushup(int rt)
{
sum1[rt]=(sum1[rt<<1]+sum1[rt<<1|1])%MOD;
sum2[rt]=(sum2[rt<<1]+sum2[rt<<1|1])%MOD;
}
void pushdown(int l,int r,int rt)
{
int mid=(l+r)>>1;
if(laz1[rt]!=0){
laz1[rt<<1]=(laz1[rt<<1]+laz1[rt])%MOD;
laz1[rt<<1|1]=(laz1[rt<<1|1]+laz1[rt])%MOD;
sum2[rt<<1]=(sum2[rt<<1]+1ll*laz1[rt]*laz1[rt]*(mid-l+1)%MOD+1ll*2*laz1[rt]*sum1[rt<<1]%MOD)%MOD;
sum2[rt<<1|1]=(sum2[rt<<1|1]+1ll*laz1[rt]*laz1[rt]*(r-mid)%MOD+1ll*2*laz1[rt]*sum1[rt<<1|1]%MOD)%MOD;
sum1[rt<<1]=(sum1[rt<<1]+1ll*(mid-l+1)*laz1[rt]%MOD)%MOD;
sum1[rt<<1|1]=(sum1[rt<<1|1]+1ll*(r-mid)*laz1[rt]%MOD)%MOD;
laz1[rt]=0;
}
}
void build(int l,int r,int rt)
{
laz1[rt]=0;
if(l==r){
sum1[rt]=a[dfn[l]];sum2[rt]=1ll*a[dfn[l]]*a[dfn[l]]%MOD;
return ;
}
int mid=(l+r)>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
pushup(rt);
}
void update(int L,int R,int l,int r,int rt,int val)
{
if(L<=l&&R>=r){
sum2[rt]=(sum2[rt]+1ll*val*val*(r-l+1)%MOD+1ll*2*val*sum1[rt]%MOD)%MOD;
sum1[rt]=(sum1[rt]+1ll*(r-l+1)*val%MOD)%MOD;laz1[rt]=(laz1[rt]+val)%MOD;
return ;
}
int mid=(l+r)>>1;
pushdown(l,r,rt);
if(L<=mid){
update(L,R,l,mid,rt<<1,val);
}
if(R>mid){
update(L,R,mid+1,r,rt<<1|1,val);
}
pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
if(L<=l&&R>=r){
return sum2[rt];
}
int mid=(l+r)>>1;
pushdown(l,r,rt);
int ans=0;
if(L<=mid){
ans=(ans+query(L,R,l,mid,rt<<1))%MOD;
}
if(R>mid){
ans=(ans+query(L,R,mid+1,r,rt<<1|1))%MOD;
}
return ans;
}
int main()
{
mem(head,-1);
int n,q,u,v,opt;
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<n;i++){
scanf("%d%d",&u,&v);
add(u,v);add(v,u);
}
dfs(1,-1);
build(1,n,1);
while(q--){
scanf("%d",&opt);
if(opt==1){
scanf("%d%d",&u,&v);
update(in[u],out[u],1,n,1,v);
}
else{
scanf("%d",&u);
printf("%d\n",query(in[u],out[u],1,n,1));
}
}
return 0;
}