牛客小白月賽9: D. 樹上求和(dfs序+線段樹)
阿新 • • 發佈:2018-11-23
連結: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; }