1. 程式人生 > >【題解】CF#474(Div.1+Div.2) H-Santa's Gift

【題解】CF#474(Div.1+Div.2) H-Santa's Gift

col 一個 long long 不同 數據結構 -a san 不同的 bits

  好久沒有寫過數據結構題目了,果然還是太不自信。實際上就是要求統計一個式子:

  \(\sum (c[k]*p[k] - C)^{2}\)

拆開,分別統計和與平方和

\(co[k] * \sum p[k]^{2} - 2 * C * co[k] \sum p[k] + \sum C ^{2}\)

顯然可以用樹鏈剖分 + 線段樹維護

平方和在區間 + 1的時候直接用 \((x + 1) ^ {2} = x^2 + 2 * x + 1\) 計算即可。

  至於不同的口味的問題,我們給每個口味都開一線段樹,動態開點~聽起來雖然復雜,但代碼實際上超短?????

#include <bits/stdc++.h>
using
namespace std; #define maxn 3000000 #define int long long #define db double int n, m, q, C, cnt, f[maxn], co[maxn], dfn[maxn]; int size[maxn], hson[maxn], top[maxn], fa[maxn]; int root[maxn], mark[maxn * 2], cal[maxn * 2], cal2[maxn * 2], son[maxn * 2][2]; int read() { int x = 0, k = 1;
char c; c = getchar(); while(c < 0 || c > 9) { if(c == -) k = -1; c = getchar(); } while(c >= 0 && c <= 9) x = x * 10 + c - 0, c = getchar(); return x * k; } struct edge { int cnp, to[maxn], last[maxn], head[maxn]; edge() { cnp = 2; } void
add(int u, int v) { to[cnp] = v, last[cnp] = head[u], head[u] = cnp ++; } }E1; void dfs(int u) { size[u] = 1; int mx = 0, hs = 0; for(int i = E1.head[u]; i; i = E1.last[i]) { int v = E1.to[i]; fa[v] = u; dfs(v); size[u] += size[v]; if(size[v] >= mx) mx = size[v], hs = v; } hson[u] = hs; } void dfs2(int u, int anc) { dfn[u] = ++ cnt, top[u] = anc; if(hson[u]) dfs2(hson[u], anc); for(int i = E1.head[u]; i; i = E1.last[i]) if(E1.to[i] != hson[u]) dfs2(E1.to[i], E1.to[i]); } void Add(int &p, int l, int r, int x) { if(!p) p = ++ cnt; mark[p] += x; cal2[p] += cal[p] * x + (r - l + 1) * x * x; cal[p] += (r - l + 1) * x * 2; } void Push_down(int p, int l, int r) { int mid = (l + r) >> 1; if(!mark[p]) return; Add(son[p][0], l, mid, mark[p]); Add(son[p][1], mid + 1, r, mark[p]); mark[p] = 0; } void Push_Up(int p) { int l = son[p][0], r = son[p][1]; cal2[p] = cal2[l] + cal2[r]; cal[p] = cal[l] + cal[r]; } void Update(int &p, int l, int r, int L, int R, int x) { if(L > R || l > r) return; if(!p) p = ++ cnt; if(L <= l && R >= r) { Add(p, l, r, x); return; } Push_down(p, l, r); int mid = (l + r) >> 1; if(L <= mid) Update(son[p][0], l, mid, L, R, x); if(R > mid) Update(son[p][1], mid + 1, r, L, R, x); Push_Up(p); } void T_Update(int k, int u, int x) { for(; u; u = fa[top[u]]) Update(root[k], 1, n, dfn[top[u]], dfn[u], x); } int Cal(int p) { return co[p] * co[p] * cal2[root[p]] - cal[root[p]] * C * co[p] + n * C * C; } signed main() { n = read(), m = read(), q = read(), C = read(); for(int i = 1; i <= n; i ++) f[i] = read(); for(int i = 2; i <= n; i ++) { int x = read(); E1.add(x, i); } for(int i = 1; i <= m; i ++) co[i] = read(); dfs(1), dfs2(1, 1), cnt = m; for(int i = 1; i <= m; i ++) root[i] = i; for(int i = 1; i <= n; i ++) T_Update(f[i], i, 1); for(int i = 1; i <= q; i ++) { int opt = read(); if(opt == 1) { int x = read(), k = read(); T_Update(f[x], x, -1), T_Update(f[x] = k, x, 1); } else { int k = read(); printf("%lf\n", (db) Cal(k) / (db) n); } } return 0; }

【題解】CF#474(Div.1+Div.2) H-Santa's Gift