Sample Inputc++
84
131
27
84spa
很是模板的樹上帶修莫隊code
真的很裸blog
直接暴力維護就能夠了ip
注意一下詢問的第二關鍵字是第二個節點所在塊,第三關鍵字是時間,否則jmr說會出鍋input
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N = 1e5 + 10; int n, m, q, col[N], c[N]; int dfn[N], dfn_ind = 0; int dep[N], fa[N][20]; int tot = 0, head[N]; ll v[N], w[N], nowans = 0; int top = 0, st[N << 1], bel[N]; int siz_block = 2000, cnt_block = 0; int num[N], vis[N]; struct Query { int u, v, id; ll ans; } Q[N]; bool cmp1(const Query &a, const Query &b) { if (bel[a.u] != bel[b.u]) return bel[a.u] < bel[b.u]; if (bel[a.v] != bel[b.v]) return bel[a.v] < bel[b.v]; return a.id < b.id; } bool cmp2(const Query &a, const Query &b) { return a.id < b.id; } struct Modify { int pos, bef, aft, id; } M[N << 1]; struct Edge { int v, nxt; } E[N << 1]; void addedge(int u, int v) { E[++tot] = (Edge) {v, head[u]}; head[u] = tot; } int dfs(int u) { int siz = 0; dfn[u] = ++dfn_ind; for (int i = 1; i <= 18; i++) fa[u][i] = fa[fa[u][i - 1]][i - 1]; for (int i = head[u]; i; i = E[i].nxt) { int v = E[i].v; if (v == fa[u][0]) continue; fa[v][0] = u; dep[v] = dep[u] + 1; siz += dfs(v); if (siz >= siz_block) { ++cnt_block; while (siz) { bel[st[top--]] = cnt_block; --siz; } } } st[++top] = u; return siz + 1; } int lca(int x, int y) { if (dep[x] < dep[y]) swap(x, y); int delta = dep[x] - dep[y]; for (int i = 0; i <= 18; i++) if ((delta >> i) & 1) x = fa[x][i]; if (x == y) return x; for (int i = 18; i >= 0; i--) { if (fa[x][i] != fa[y][i]) { x = fa[x][i]; y = fa[y][i]; } } return fa[x][0]; } void reverse(int x) { if (vis[x]) { nowans -= w[num[col[x]]] * v[col[x]]; num[col[x]]--; } else { num[col[x]]++; nowans += w[num[col[x]]] * v[col[x]]; } vis[x] ^= 1; } void solve(int x, int y) { while (x != y) { if (dep[x] > dep[y]) { reverse(x); x = fa[x][0]; } else { reverse(y); y = fa[y][0]; } } } int main() { #ifdef dream_maker freopen("input.txt", "r", stdin); #endif scanf("%d %d %d", &n, &m, &q); for (int i = 1; i <= m; i++) scanf("%lld", &v[i]); for (int i = 1; i <= n; i++) scanf("%lld", &w[i]); for (int i = 1; i < n; i++) { int u, v; scanf("%d %d", &u, &v); addedge(u, v); addedge(v, u); } for (int i = 1; i <= n; i++) { scanf("%d", &col[i]); c[i] = col[i]; } int cntq = 0, cntm = 0; for (int i = 1; i <= q; i++) { int typ; scanf("%d", &typ); if (typ) { ++cntq; Q[cntq].id = i; scanf("%d %d", &Q[cntq].u, &Q[cntq].v); } else { ++cntm; M[cntm].id = i; int x, y; scanf("%d %d", &x, &y); M[cntm].pos = x; M[cntm].bef = c[x]; c[x] = y; M[cntm].aft = c[x]; } } dfs(1); ++cnt_block; while (top) { bel[st[top--]] = cnt_block; } sort(Q + 1, Q + cntq + 1, cmp1); int cur = 0; for (int i = 1; i <= cntq; i++) { while (cur < cntm && M[cur + 1].id <= Q[i].id) { ++cur; if (vis[M[cur].pos]) { nowans -= w[num[col[M[cur].pos]]] * v[col[M[cur].pos]]; num[col[M[cur].pos]]--; } col[M[cur].pos] = M[cur].aft; if (vis[M[cur].pos]) { num[col[M[cur].pos]]++; nowans += w[num[col[M[cur].pos]]] * v[col[M[cur].pos]]; } } while (cur >= 1 && M[cur].id >= Q[i].id) { if (vis[M[cur].pos]) { nowans -= w[num[col[M[cur].pos]]] * v[col[M[cur].pos]]; num[col[M[cur].pos]]--; } col[M[cur].pos] = M[cur].bef; if (vis[M[cur].pos]) { num[col[M[cur].pos]]++; nowans += w[num[col[M[cur].pos]]] * v[col[M[cur].pos]]; } --cur; } if (i == 1) { solve(Q[i].u, Q[i].v); } else { solve(Q[i].u, Q[i - 1].u); solve(Q[i].v, Q[i - 1].v); } int t = lca(Q[i].u, Q[i].v); reverse(t); Q[i].ans = nowans; reverse(t); } sort(Q + 1, Q + cntq + 1, cmp2); for (int i = 1; i <= cntq; i++) printf("%lld\n", Q[i].ans); return 0; }