写了一下午太不容易了。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cctype>
#define Debug(x) std::cerr << #x << "=" << x << std::endl
typedef long long ll;
const int N = 2e5 + 5;
const int M = 1e6 + 5;
void read(int &x){
x = 0;int f = 1;char c = getchar();
for(;!isdigit(c);c = getchar())if(c == '-')f = -1;
for(;isdigit(c);c = getchar())x = (x << 1) + (x << 3) + c - '0';
x *= f;
}
int n,m,Q,block;
int v[N],w[N],seq[N << 1],fa[N][20],cnt[M],top,first[N],last[N],deep[N],c[N],st[N];
ll ans[N];
struct Edge{
int node;
int next;
Edge(int node = 0,int next = 0):node(node),next(next){}
}edge[N << 1];
int head[N],tot = 1;
void add_edge(int u,int v){
edge[++tot] = Edge(v,head[u]);
head[u] = tot;
}
struct Query{
int id,l,r,p,t;
Query(int id = 0,int l = 0,int r = 0,int p = 0,int t = 0):id(id),l(l),r(r),p(p),t(t){}
bool operator < (const Query& P){
return (l / block) ^ (P.l / block) ? l < P.l : (r / block) ^ (P.r / block) ? r < P.r : t < P.t;
}
}q[N];
struct Update{
int id,x,y;
}upd[N];
void euper(int u,int p){
seq[++top] = u;
first[u] = top;
for(int i = head[u];i;i = edge[i].next){
int v = edge[i].node;
if(v != p)euper(v,u);
}
seq[++top] = u;
last[u] = top;
}
void dfs(int u,int p){
deep[u] = deep[p] + 1;
fa[u][0] = p;
for(int i = 1;deep[u] >= (1 << i);i++){
fa[u][i] = fa[fa[u][i - 1]][i - 1];
}
for(int i = head[u];i;i = edge[i].next){
int v = edge[i].node;
if(!deep[v])dfs(v,u);
}
}
inline int lca(int u,int v){
if(deep[u] < deep[v])std::swap(u,v);
for(int i = 18;i >= 0;i--){
if(deep[fa[u][i]] >= deep[v]){
u = fa[u][i];
}
}
if(u == v)return u;
for(int i = 18;i >= 0;i--){
if(fa[u][i] == fa[v][i])continue;
u = fa[u][i];
v = fa[v][i];
}
return fa[u][0];
}
inline ll add(int x){
st[x] ^= 1;
if(st[x]){
++cnt[c[x]];
return (ll)v[c[x]] * (ll)w[cnt[c[x]]];
}
else {
ll res = (ll)v[c[x]] * (ll)w[cnt[c[x]]];
--cnt[c[x]];
return -res;
}
}
inline ll amend(int t,int x){
ll res = 0;
if(st[upd[t].x] == 0){
std::swap(upd[t].y,c[upd[t].x]);
return res;
}
// if(q[x].l <= first[upd[t].x] && q[x].r >= last[upd[t].x] ){
// std::swap(upd[t].y,c[upd[t].x]);
// return res;
// }
// else if(q[x].l > first[upd[t].x] && q[x].r < last[upd[t].x]){
// std::swap(upd[t].y,c[upd[t].x]);
// return res;
// }
else {
++cnt[upd[t].y];
res += (ll)v[upd[t].y] * w[cnt[upd[t].y]];
res -= (ll)v[c[upd[t].x]] * w[cnt[c[upd[t].x]]];
--cnt[c[upd[t].x]];
std::swap(upd[t].y,c[upd[t].x]);
return res;
}
}
int main(int argc,char *argv[]){
read(n);read(m);read(Q);
for(int i = 1;i <= m;i++){
read(v[i]);
}
for(int i = 1;i <= n;i++){
read(w[i]);
}
for(int i = 1;i < n;i++){
int u,v;
read(u);
read(v);
add_edge(u,v);
add_edge(v,u);
}
for(int i = 1;i <= n;i++){
read(c[i]);
}
euper(1,0);
dfs(1,0);
int qcnt = 0,ucnt = 0;
for(int i = 1;i <= Q;i++){
int type,x,y;
read(type);
read(x);
read(y);
if(type){
if(first[x] > first[y])std::swap(x,y);
int p = lca(x,y);
if(x == p)++qcnt,q[qcnt] = Query(qcnt,first[x],first[y],0,ucnt);
else ++qcnt,q[qcnt] = Query(qcnt,last[x],first[y],p,ucnt);
}
else {
upd[++ucnt].id = ucnt;
upd[ucnt].x = x;
upd[ucnt].y = y;
}
}
block = pow((double)top,0.666);
std::sort(q + 1,q + qcnt + 1);
ll res = 0;
int ql = 1,qr = 0,qt = 0;
// for(int i = 1;i <= qcnt;i++){
// printf("id = %d l = %d r = %d p = %d t = %d\n",q[i].id,q[i].l,q[i].r,q[i].p,q[i].t);
// }
for(int i = 1;i <= qcnt;i++){
int id = q[i].id,l = q[i].l,r = q[i].r,t = q[i].t;
while(ql < l)res += add(seq[ql++]);
while(ql > l)res += add(seq[--ql]);
while(qr > r)res += add(seq[qr--]);
while(qr < r)res += add(seq[++qr]);
if(q[i].p)res += add(q[i].p);
while(t < qt)res += amend(qt--,i);
while(t > qt)res += amend(++qt,i);
ans[id] = res;
if(q[i].p)res += add(q[i].p);
}
for(int i = 1;i <= qcnt;i++)printf("%lld\n",ans[i]);
return 0;
}