链接:https://ac.nowcoder.com/acm/contest/275/D
来源:牛客网
题目描述
给你一棵根为1的有N个节点的树,以及Q次操作。
每次操作诸如:
1 x y:将节点x所在的子树的所有节点的权值加上y
2 x:询问x所在子树的所有节点的权值的平方和,答案模23333后输出
输入描述:
第一行两个整数N,Q 第二行N个整数,第i个表示节点i的初始权值 接下来N-1行每行两个整数u,v,表示u和v之间存在一条树边 接下来Q行每行一个操作,格式如题目描述
输出描述:
对于每个询问操作,输出一行一个整数,表示答案在模23333后的结果
输入
5 5 0 0 0 0 0 1 2 1 3 3 4 3 5 1 1 3 1 3 7 1 4 5 1 5 6 2 1
输出
599
两个模板往上拍就好
我这个还额外支持区间乘操作
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<string>
#include<math.h>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
#define LL long long
#define mod 23333
int cnt, a[100005], b[100005], in[100005], out[100005];
vector<int> G[100005];
typedef struct Tree
{
LL x;
LL X;
}Tree;
Tree tre[500005], lazy[500005];
void Create(int l, int r, int x)
{
int m;
lazy[x].X = 1;
if(l==r)
{
tre[x].x = b[l]%mod;
tre[x].X = (tre[x].x*tre[x].x)%mod;
return;
}
m = (l+r)/2;
Create(l, m, x*2);
Create(m+1, r, x*2+1);
tre[x].x = (tre[x*2].x+tre[x*2+1].x)%mod;
tre[x].X = (tre[x*2].X+tre[x*2+1].X)%mod;
}
void GaoX(int l, int r, int x, LL val)
{
tre[x].x = tre[x].x*val%mod;
tre[x].X = tre[x].X*val%mod*val%mod;
if(l!=r)
lazy[x].X = lazy[x].X*val%mod, lazy[x].x = lazy[x].x*val%mod;
}
void GaoAdd(int l, int r, int x, LL val)
{
tre[x].X = (tre[x].X+val*val%mod*(r-l+1)%mod+2*val*tre[x].x)%mod;
tre[x].x = (tre[x].x+val*(r-l+1))%mod;
if(l!=r)
lazy[x].x = (lazy[x].x+val)%mod;
}
void Update(int l, int r, int x, int a, int b, LL c, int op)
{
int m;
if(l>=a && r<=b)
{
if(op==4)
GaoAdd(l, r, x, c);
else
GaoX(l, r, x, c);
return;
}
m = (l+r)/2;
if(lazy[x].X!=1)
GaoX(l, m, x*2, lazy[x].X), GaoX(m+1, r, x*2+1, lazy[x].X), lazy[x].X = 1;
if(lazy[x].x)
GaoAdd(l, m, x*2, lazy[x].x), GaoAdd(m+1, r, x*2+1, lazy[x].x), lazy[x].x = 0;
if(a<=m)
Update(l, m, x*2, a, b, c, op);
if(b>=m+1)
Update(m+1, r, x*2+1, a, b, c, op);
tre[x].x = (tre[x*2].x+tre[x*2+1].x)%mod;
tre[x].X = (tre[x*2].X+tre[x*2+1].X)%mod;
}
LL Query(int l, int r, int x, int a, int b, int op)
{
int m;
LL ans = 0;
if(l>=a && r<=b)
{
if(op==1)
return tre[x].x;
else
return tre[x].X;
}
m = (l+r)/2;
if(lazy[x].X!=1)
GaoX(l, m, x*2, lazy[x].X), GaoX(m+1, r, x*2+1, lazy[x].X), lazy[x].X = 1;
if(lazy[x].x)
GaoAdd(l, m, x*2, lazy[x].x), GaoAdd(m+1, r, x*2+1, lazy[x].x), lazy[x].x = 0;
if(a<=m)
ans = (ans+Query(l, m, x*2, a, b, op))%mod;
if(b>=m+1)
ans = (ans+Query(m+1, r, x*2+1, a, b, op))%mod;
return ans;
}
void Sech(int u, int p)
{
int i, v;
in[u] = ++cnt;
b[cnt] = a[u];
for(i=0;i<G[u].size();i++)
{
v = G[u][i];
if(v==p)
continue;
Sech(v, u);
}
out[u] = cnt;
}
int main(void)
{
int n, T, i, x, y, op;
scanf("%d%d", &n, &T);
for(i=1;i<=n;i++)
scanf("%d", &a[i]);
for(i=1;i<=n-1;i++)
{
scanf("%d%d", &x, &y);
G[x].push_back(y);
G[y].push_back(x);
}
Sech(1, 0);
Create(1, n, 1);
while(T--)
{
scanf("%d", &op);
if(op==1)
{
scanf("%d%d", &x, &y);
Update(1, n, 1, in[x], out[x], y, 4);
}
else
{
scanf("%d", &x);
printf("%lld\n", Query(1, n, 1, in[x], out[x], 2));
}
}
return 0;
}