其实这是我打的第二道题……一眼可以用树剖做,于是就是树链剖分的板子题。
但其实似乎只求子树用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; }