Candyland 有一座糖果公园,公园里不只有美丽的风景、好玩的游乐项目,还有许多免费糖果的发放点,这引来了许多贪吃的小朋友来糖果公园游玩。html
糖果公园的结构十分奇特,它由 \(n\) 个游览点构成,每一个游览点都有一个糖果发放处,咱们能够依次将游览点编号为 \(1\) 至 \(n\)。有 \(n-1\) 条双向道路链接着这些游览点,而且整个糖果公园都是连通的,即从任何一个游览点出发均可以经过这些道路到达公园里的全部其它游览点。git
糖果公园所发放的糖果种类很是丰富,总共有 \(m\) 种,它们的编号依次为 \(1\) 至 \(m\)。每个糖果发放处都只发放某种特定的糖果,咱们用 \(C_i\) 来表示 \(i\) 号游览点的糖果。spa
来到公园里游玩的游客都不喜欢走回头路,他们老是从某个特定的游览点出发前往另外一个特定的游览点,并游览途中的景点,这条路线必定是惟一的。他们通过每一个游览点,均可以品尝到一颗对应种类的糖果。code
你们对不一样类型糖果的喜好程度都不尽相同。 根据游客们的反馈打分,咱们获得了糖果的美味指数, 第 \(i\) 种糖果的美味指数为 \(V_i\) 。另外,若是一位游客反复地品尝同一种类的糖果,他确定会以为有一些腻。根据量化统计,咱们获得了游客第 \(i\) 次品尝某类糖果的新奇指数 \(W_i\) 。若是一位游客第 \(i\) 次品尝第 \(j\) 种糖果,那么他的愉悦指数 \(H\) 将会增长对应的美味指数与新奇指数的乘积,即 \(V_j×W_i\) 。这位游客游览公园的愉悦指数最终将是这些乘积的和。htm
固然,公园中每一个糖果发放点所发放的糖果种类不必定是一成不变的。有时,一些糖果点所发放的糖果种类可能会更改(也只会是 \(m\) 种中的一种),这样的目的是可以让游客们老是感觉到惊喜。blog
糖果公园的工做人员小 A 接到了一个任务,那就是根据公园最近的数据统计出每位游客游玩公园的愉悦指数。但数学很差的小 A 一看到密密麻麻的数字就以为头晕,做为小 A 最好的朋友,你决定帮他一把。get
从文件 park.in 中读入数据。qt
第一行包含三个正整数 \(n\), \(m\), \(q\), 分别表示游览点个数、 糖果种类数和操做次数。数学
第二行包含 \(m\) 个正整数 \(V_1,V_2,...,V_m\) 。string
第三行包含 \(n\) 个正整数 \(W_1,W_2,...,W_n\) 。
第四行到第 \(n+2\) 行,每行包含两个正整数 \(A_i,B_i\) ,表示这两个游览点之间有路径能够直接到达。
第 \(n+3\) 行包含 \(n\) 个正整数 \(C_1,C_2,C_n\) 。
接下来 \(q\) 行, 每行包含三个整数 \(Type\), \(x\), \(y\),表示一次操做:
若 \(Type\) 为 \(0\),则 \(1 ≤ x ≤ n\), \(1 ≤ y ≤ m\),表示将编号为 \(x\) 的游览点发放的糖果类型改成 \(y\);
若 \(Type\) 为 \(1\),则 \(1 ≤ x, y ≤ n\),表示对出发点为 \(x\),终止点为 \(y\) 的路线询问愉悦指数。
输出到文件 park.out 中。
按照输入的前后顺序,对于每一个 \(Type\) 为 \(1\) 的操做输出一行,用一个正整数表示答案。
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
84 131 27 84
树上莫队+带修莫队=树上带修莫队,若是不懂能够看这里
莫队添加数值时,添加的数值(添加的结点发的糖,记为\(c\))对答案的贡献为\(V_c × W_{cnt_c}\),在端点、修改点、lca暴力添加便可。删除亦然。
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define maxn 200200 #define ll long long int cnt[maxn], aa[maxn], belong[maxn], inp[maxn], n, m, Q, ncnt, size, bnum, w[maxn], v[maxn], ccnt, qcnt; int val[maxn], fa[maxn][30], depth[maxn], head[maxn], ecnt; int fir[maxn], la[maxn], vis[maxn]; int l = 1, r = 0, t = 0; ll now, ans[maxn]; struct edge { int to, next; } e[maxn]; void adde(int u, int v) { e[++ecnt] = (edge){v, head[u]}; head[u] = ecnt; e[++ecnt] = (edge){u, head[v]}; head[v] = ecnt; } void dfs(int x) { aa[++ncnt] = x; fir[x] = ncnt; for(int k = head[x]; k; k = e[k].next) { int to = e[k].to; if(depth[to]) continue; depth[to] = depth[x] + 1; fa[to][0] = x; for(int i = 1; (1 << i) <= depth[to]; ++i) fa[to][i] = fa[fa[to][i - 1]][i - 1]; dfs(to); } aa[++ncnt] = x; la[x] = ncnt; } int getlca(int u, int v) { if(depth[u] < depth[v]) swap(u, v); for(int i = 20; i + 1; --i) if(depth[fa[u][i]] >= depth[v]) u = fa[u][i]; if(u == v) return u; for(int i = 20; i + 1; --i) if(fa[u][i] != fa[v][i]) u = fa[u][i], v = fa[v][i]; return fa[u][0]; } struct query { int l, r, id, lca, t; } q[maxn]; int cmp(query a, query b) { return (belong[a.l] ^ belong[b.l]) ? belong[a.l] < belong[b.l] : ((belong[a.r] ^ belong[b.r]) ? belong[a.r] < belong[b.r] : a.t < b.t ); } inline void add(int pos) { now += 1ll * v[val[pos]] * w[++cnt[val[pos]]]; } inline void del(int pos) { now -= 1ll * v[val[pos]] * w[cnt[val[pos]]--]; } inline void work(int pos) { vis[pos] ? del(pos) : add(pos); vis[pos] ^= 1; } struct change { int pos, val; } ch[maxn]; void modify(int x) { if(vis[ch[x].pos]) { work(ch[x].pos); swap(val[ch[x].pos], ch[x].val); work(ch[x].pos); } else swap(val[ch[x].pos], ch[x].val); } #define isdigit(x) ((x) >= '0' && (x) <= '9') inline int read() { int res = 0; char c = getchar(); while(!isdigit(c)) c = getchar(); while(isdigit(c)) res = (res << 1) + (res << 3) + (c ^ 48), c = getchar(); return res; } int main() { n = read(), m = read(), Q = read(); for(int i = 1; i <= m; ++i) v[i] = read(); for(int i = 1; i <= n; ++i) w[i] = read(); for(int i = 1; i < n; ++i) { int u = read(), v = read(); adde(u, v); } for(int i = 1; i <= n; ++i) val[i] = read(); depth[1] = 1; dfs(1); size = pow(ncnt, 2.0 / 3.0); bnum = ceil((double)ncnt / size); for(int i = 1; i <= bnum; ++i) for(int j = size * (i - 1) + 1; j <= i * size; ++j) belong[j] = i; for(int i = 1; i <= Q; ++i) { int opt = read(), a = read(), b = read(); if(opt) { int lca = getlca(a, b); q[++qcnt].t = ccnt; q[qcnt].id = qcnt; if(fir[a] > fir[b]) swap(a, b); if(a == lca) q[qcnt].l = fir[a], q[qcnt].r = fir[b]; else q[qcnt].l = la[a], q[qcnt].r = fir[b], q[qcnt].lca = lca; } else { ch[++ccnt].pos = a; ch[ccnt].val = b; } } sort(q + 1, q + qcnt + 1, cmp); for(int i = 1; i <= qcnt; ++i) { int ql = q[i].l, qr = q[i].r, qt = q[i].t, qlca = q[i].lca; while(l < ql) work(aa[l++]); while(l > ql) work(aa[--l]); while(r < qr) work(aa[++r]); while(r > qr) work(aa[r--]); while(t < qt) modify(++t); while(t > qt) modify(t--); if(qlca) work(qlca); ans[q[i].id] = now; if(qlca) work(qlca); } for(int i = 1; i <= qcnt; ++i) printf("%lld\n", ans[i]); return 0; }