其实这是我打的第二道题……一眼可以用树剖做,于是就是树链剖分的板子题。
但其实似乎只求子树用dfs序就可以……?是我蠢了。
线段树维护平方和也是老套路了:
#include <cstdio>
#include <ctype.h>
#define DEBUG
#define int long long
const int bufSize = 1e6;
inline char nc()
{
#ifdef DEBUG
return getchar();
#endif
static char buf[bufSize],*p1 = buf,*p2 = buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,bufSize,stdin),p1==p2)?EOF:*p1++;
}
template<typename T>
inline T read(T &r)
{
static char c;
r=0;
for(c = nc();!isdigit(c);) c = nc();
for(;isdigit(c);c=nc()) r = r * 10 + c - 48;
return r;
}
const int maxn = 1e5 + 100,maxm = 2e5 + 100;
int n,m;
struct node
{
int to,next;
}E[maxm];
int head[maxn];
inline void add(const int &x,const int &y)
{
static int tot = 0;
E[++tot].next = head[x],E[tot].to = y,head[x] = tot;
}
int w[maxn];
int size[maxn],fa[maxn],son[maxn],dfn[maxn],id[maxn],cnt;
long long sum[maxn<<2],tsum[maxn<<2],tag[maxn<<2];
const int mod = 23333;
#define ls p<<1
#define rs p<<1|1
inline void pushup(const int &p){sum[p] = sum[ls] + sum[rs];tsum[p] = tsum[ls] + tsum[rs];sum[p] %= mod,tsum[p] %= mod;}
inline void pushdown(const int &l,const int &r,const int &p)
{
if(!tag[p]) return;
int mid = l + r >> 1;
tsum[ls] += (mid - l + 1) * tag[p] * tag[p] + 2 * sum[ls] * tag[p];
tsum[rs] += (r - mid) * tag[p] * tag[p] + 2 * sum[rs] * tag[p];
sum[ls] += (mid - l + 1) * tag[p];
sum[rs] += (r - mid) * tag[p];
tag[ls] += tag[p],tag[rs] += tag[p];
tsum[ls] %= mod,tsum[rs] %= mod,sum[ls] %= mod,sum[rs] %= mod,tag[ls] %= mod,tag[rs] %= mod;
tag[p] = 0;
}
void build(int l,int r,int p)
{
if(l == r) return (void)(sum[p] = w[id[l]] % mod,tsum[p] = (w[id[l]] * w[id[l]]) % mod);
int mid = l + r >> 1;
build(l, mid, ls), build(mid + 1, r, rs);
pushup(p);
}
void modify(int l,int r,int p,int ll,int rr,long long k)
{
if(l >= ll && r <= rr)
{
tsum[p] += (r - l + 1) * k * k + 2 * sum[p] * k;
sum[p] += (r - l + 1) * k;
tag[p] += k;
tsum[p] %= mod,sum[p] %= mod,tag[p] %= mod;
return;
}
int mid = l + r >> 1;
pushdown(l,r,p);
if(ll <= mid) modify(l,mid,ls,ll,rr,k);
if(rr > mid) modify(mid + 1,r,rs,ll,rr,k);
pushup(p);
}
long long ask(int l,int r,int p,int ll,int rr)
{
if(l >= ll && r <= rr) return tsum[p];
int mid = l + r >> 1,ans = 0;
pushdown(l,r,p);
if(ll <= mid) ans = ask(l,mid,ls,ll,rr) % mod;
if(rr > mid) ans = (ans + ask(mid + 1,r,rs,ll,rr)) % mod;
return ans;
}
void dfs1(int u)
{
size[u] = 1;
for(int p = head[u];p;p=E[p].next)
{
int v = E[p].to;
if(v == fa[u]) continue;
fa[v] = u,dfs1(v),size[u] += size[v];
if(size[son[u]] < size[v]) son[u] = v;
}
}
void dfs2(int u)
{
dfn[u] = ++cnt;
id[cnt] = u;
if(!son[u]) return;
dfs2(son[u]);
for(int p = head[u];p;p=E[p].next)
{
int v = E[p].to;
if(v == son[u] || v == fa[u]) continue;
dfs2(v);
}
}
signed main()
{
read(n),read(m);
for(int i = 1;i<=n;++i) read(w[i]);
for(int i = 1;i<n;++i)
{
int a,b;
read(a),read(b);
add(a,b),add(b,a);
}
dfs1(1),dfs2(1);
build(1,n,1);
while(m--)
{
int opt,x,y;
read(opt),read(x);
if(opt == 1) read(y),modify(1,n,1,dfn[x],dfn[x] + size[x] - 1,y);
else printf("%lld\n",ask(1,n,1,dfn[x],dfn[x] + size[x] - 1) % mod);
}
return 0;
} 
京公网安备 11010502036488号