http://www.lydsy.com/JudgeOnline/problem.php?id=3052
树上带修莫队棵题
写完了,吐了一口老血
#include<cstdio>
#include<algorithm>
#include<cmath>
#define VIS(now) for(register int e=las[now];e;e=nxt[e])
#define FOR(i,s,t) for(register int i=s;i<=t;++i)
typedef long long ll;
using std::swap;
using std::sort;
const int N=200011;
int xu[N],v[N],w[N],a[N],hv[N];
int las[N],nxt[N],to[N],bo[N];
int dep[N],top[N],sz[N],fa[N];
int blo,dfn_num,tot,times;
int n,m,Q;
ll res;
ll ans[N];
inline void add(int x,int y){
nxt[++tot]=las[x];las[x]=tot;to[tot]=y;
}
struct qs{
int l,r,t,id;
inline bool operator<(qs A)const{
if(xu[l]/blo!=xu[A.l]/blo)return xu[l]<xu[A.l];
if(xu[r]/blo!=xu[A.r]/blo)return xu[r]<xu[A.r];
if(t/blo!=A.t/blo)return t<A.t;
return id<A.id;
}
}q[N];
struct cg{int p,x;}c[N];
inline void dfs1(int now){
sz[now]=1;
VIS(now)
if(!dep[to[e]]){
dep[to[e]]=dep[now]+1;fa[to[e]]=now;
dfs1(to[e]);sz[now]+=sz[to[e]];
}
}
inline void dfs2(int now,int chain){
xu[now]=++dfn_num;top[now]=chain;
register int i=0;
VIS(now)if(sz[to[e]]>sz[i]&&fa[now]!=to[e])i=to[e];
if(!i)return;dfs2(i,chain);
VIS(now)if(to[e]!=fa[now]&&to[e]!=i)dfs2(to[e],to[e]);
}
inline int LCA(int x,int y){
for(;top[x]!=top[y];dep[top[x]]>dep[top[y]]?x=fa[top[x]]:y=fa[top[y]]);
return dep[x]<dep[y]?x:y;
}
int t,x,y,l,r,now,lca;
inline void add(int x){
bo[x]^=1;
if(bo[x])
++hv[a[x]],res+=1ll*w[hv[a[x]]]*v[a[x]];
else
res-=1ll*w[hv[a[x]]]*v[a[x]],--hv[a[x]];
}
inline void change(int t){
int pos=c[t].p;
if(bo[pos]){
res-=1ll*w[hv[a[pos]]]*v[a[pos]],--hv[a[pos]];
++hv[c[t].x],res+=1ll*w[hv[c[t].x]]*v[c[t].x];
}
swap(a[pos],c[t].x);
}
int main(){
scanf("%d%d%d",&n,&m,&Q);
blo=pow(n,2.00/3.00);
FOR(i,1,m)scanf("%d",v+i);
FOR(i,1,n)scanf("%d",w+i);
FOR(i,2,n)scanf("%d%d",&x,&y),add(x,y),add(y,x);
FOR(i,1,n)scanf("%d",a+i);
dep[1]=1;dfs1(1);dfs2(1,1);
tot=0;
FOR(i,1,Q){
scanf("%d%d%d",&t,&x,&y);
if(t==1){
if(xu[x]>xu[y])swap(x,y);
q[++tot]=(qs){x,y,times,tot};
}
else
c[++times]=(cg){x,y};
}
sort(q+1,q+tot+1);
l=1,r=1,now=0;
FOR(i,1,tot){
lca=LCA(l,q[i].l);
for(register int j=l;j!=lca;j=fa[j])add(j);
for(register int j=q[i].l;j!=lca;j=fa[j])add(j);
lca=LCA(r,q[i].r);
for(register int j=r;j!=lca;j=fa[j])add(j);
for(register int j=q[i].r;j!=lca;j=fa[j])add(j);
lca=LCA(q[i].l,q[i].r);
add(lca);
while(now<q[i].t)change(++now);
while(now>q[i].t)change(now--);
ans[q[i].id]=res;
add(lca);
l=q[i].l;r=q[i].r;
}
FOR(i,1,tot)printf("%lld\n",ans[i]);
return 0;
}