传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3052
【题解】
树上莫队+带修改,分块大小n^(2/3)即可。
复杂度O(n^(5/3))
# include <math.h> # include <stdio.h> # include <string.h> # include <iostream> # include <algorithm> // # include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 2e5 + 10, N = 1e5 + 10; const int mod = 1e9+7; # define RG register # define ST static inline int getint() { int x = 0, f = 1; char ch = getchar(); while(!isdigit(ch)) { if(ch == '-') f = 0; ch = getchar(); } while(isdigit(ch)) { x = (x<<3) + (x<<1) + ch - '0'; ch = getchar(); } return f ? x : -x; } int n, m, Q, V[N], B[N], C[N], t[N]; int head[N], nxt[M], to[M], tot = 0; inline void add(int u, int v) { ++tot; nxt[tot] = head[u]; head[u] = tot; to[tot] = v; } inline void adde(int u, int v) { add(u, v), add(v, u); } int BLOCK, bl[M]; struct pa { int x, y, p, t; pa() {} pa(int x, int y, int p, int t) : x(x), y(y), p(p), t(t) {} friend bool operator < (pa a, pa b) { return bl[a.x] < bl[b.x] || (bl[a.x] == bl[b.x] && bl[a.y] < bl[b.y]) || (bl[a.x] == bl[b.x] && bl[a.y] == bl[b.y] && a.t < b.t); } }q[M]; struct paa { int x, oc, nc, t; paa() {} paa(int x, int oc, int nc, int t) : x(x), oc(oc), nc(nc), t(t) {} }p[M]; int pn, qn; int beg[N], end[N], dfn[M], DFN = 0; int fa[N][18], dep[N]; inline void dfs(int x, int fat = 0) { beg[x] = ++DFN; dfn[DFN] = x; dep[x] = dep[fat] + 1; fa[x][0] = fat; for (int i=1; i<=17; ++i) fa[x][i] = fa[fa[x][i-1]][i-1]; for (int i=head[x]; i; i=nxt[i]) { if(to[i] == fat) continue; dfs(to[i], x); } end[x] = ++DFN; dfn[DFN] = x; } inline int lca(int u, int v) { if(dep[u] < dep[v]) swap(u, v); for (int i=17; ~i; --i) if((dep[u] - dep[v]) & (1<<i)) u = fa[u][i]; if(u == v) return u; for (int i=17; ~i; --i) if(fa[u][i] != fa[v][i]) u = fa[u][i], v = fa[v][i]; return fa[u][0]; } inline bool IN(int L, int R, int x) { return L <= x && x <= R; } ll ans[M]; bool ban[M]; int ti[M]; ll cnt; inline void ADD(int c) { t[c] ++; cnt += (ll)V[c] * B[t[c]]; } inline void DEL(int c) { cnt -= (ll)V[c] * B[t[c]]; t[c] --; } inline void doit(int pos) { if(ti[pos] == 0) ADD(C[pos]); else DEL(C[pos]); ti[pos] ^= 1; } int main() { cin >> n >> m >> Q; for (int i=1; i<=m; ++i) V[i] = getint(); for (int i=1; i<=n; ++i) B[i] = getint(); for (int i=1, u, v; i<n; ++i) { u = getint(), v = getint(); adde(u, v); } dfs(1); BLOCK = pow(n, 2.0/3.0); for (int i=1; i<=DFN; ++i) bl[i] = (i-1)/BLOCK + 1; for (int i=1; i<=n; ++i) t[i] = C[i] = getint(); for (int i=1, o, tx, ty; i<=Q; ++i) { o = getint(); tx = getint(), ty = getint(); if(o) { int LCA = lca(tx, ty); if(beg[tx] > beg[ty]) swap(tx, ty); if(LCA == tx) q[++qn] = pa(beg[tx], beg[ty], 0, i); else q[++qn] = pa(end[tx], beg[ty], LCA, i); // cout << LCA << endl; } else { p[++pn] = paa(tx, t[tx], ty, i); t[tx] = ty; ban[i] = 1; } } sort(q+1, q+qn+1); // puts("======p======"); // for (int i=1; i<=pn; ++i) printf("x = %d, oc = %d, nc = %d, t = %d ", p[i].x, p[i].oc, p[i].nc, p[i].t); // puts("======q======"); // for (int i=1; i<=qn; ++i) printf("x = %d, y = %d, lca = %d, t = %d ", q[i].x, q[i].y, q[i].p, q[i].t); // puts("============="); for (int i=1; i<=n; ++i) t[i] = ti[i] = 0; int L = 1, R = 0; for (int i=1, j=1; i<=qn; ++i) { while(j <= pn && q[i].t > p[j].t) { if(IN(L, R, beg[p[j].x]) ^ IN(L, R, end[p[j].x])) ADD(p[j].nc), DEL(p[j].oc); C[p[j].x] = p[j].nc; ++j; } while(j-1 >= 1 && q[i].t < p[j-1].t) { --j; if(IN(L, R, beg[p[j].x]) ^ IN(L, R, end[p[j].x])) ADD(p[j].oc), DEL(p[j].nc); C[p[j].x] = p[j].oc; } // printf("i = %d, j = %d ", i, j); while(L < q[i].x) doit(dfn[L]), ++L; while(L > q[i].x) --L, doit(dfn[L]); while(R < q[i].y) ++R, doit(dfn[R]); while(R > q[i].y) doit(dfn[R]), --R; if(q[i].p) doit(q[i].p); ans[q[i].t] = cnt; if(q[i].p) doit(q[i].p); } for (int i=1; i<=Q; ++i) if(!ban[i]) printf("%lld ", ans[i]); return 0; } /* 4 3 5 1 9 2 7 6 5 1 2 3 3 1 3 4 1 2 3 2 1 1 2 1 4 2 0 2 1 1 1 2 1 4 2 */