题解
首先我们发现吃糖的顺序是不会影响答案的
影响答案的是每种糖的个数
所以我们可以直接利用树上莫队来做
树上莫队有两种写法,一种是在括号序列上进行莫队,另一种就直接对树进行分块,在树上进行莫队
这里写的是在括号序列上的莫队
如何带修改呢
我们维护一种有三个指针的莫队(比普通的莫队多一个时间指针)
类似普通的莫队一样移动指针就可以了
只不过块的大小要调为n^(2/3)
具体的时间复杂度分析可以看这篇博客
代码:
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
inline int gi()
{
char c;int num=0,flg=1;
while((c=getchar())<'0'||c>'9')if(c=='-')flg=-1;
while(c>='0'&&c<='9'){num=num*10+c-48;c=getchar();}
return num*flg;
}
#define N 200005
#define LL long long
int fir[N],to[N],nxt[N],cnt;
void adde(int a,int b)
{
to[++cnt]=b;nxt[cnt]=fir[a];fir[a]=cnt;
to[++cnt]=a;nxt[cnt]=fir[b];fir[b]=cnt;
}
int fa[N],siz[N],top[N],son[N],dep[N];
int L[N],R[N],pos[N],dc;
void dfs1(int u)
{
siz[u]=1;dep[u]=dep[fa[u]]+1;
for(int v,p=fir[u];p;p=nxt[p]){
if((v=to[p])!=fa[u]){
fa[v]=u;dfs1(v);
siz[u]+=siz[v];
if(siz[son[u]]<siz[v])
son[u]=v;
}
}
}
void dfs2(int u)
{
L[u]=++dc;pos[dc]=u;
if(son[u])top[son[u]]=top[u],dfs2(son[u]);
for(int v,p=fir[u];p;p=nxt[p])
if((v=to[p])!=fa[u]&&v!=son[u])
top[v]=v,dfs2(v);
R[u]=++dc;pos[dc]=u;
}
int LCA(int x,int y)
{
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
x=fa[top[x]];
}
return dep[x]<dep[y]?x:y;
}
int bel[N],cha[N][3],tcnt,qcnt;
struct node{
int l,r,t,id;
bool operator < (const node &T)const{
return bel[l]==bel[T.l] ? ( bel[r]==bel[T.r] ? (((bel[l]^bel[r])&1)?t<T.t:t>T.t) : ((bel[l]&1)?bel[r]<bel[T.r]:bel[r]>bel[T.r]) ) : bel[l]<bel[T.l];
}
}q[N];
LL ans[N],sum;
int V[N],W[N],C[N],con[N];bool vis[N];
void update(int x)
{
if(vis[x])sum-=1ll*V[C[x]]*(W[con[C[x]]--]);
else sum+=1ll*V[C[x]]*(W[++con[C[x]]]);
vis[x]^=1;
}
void modify(int x,int y)
{
if(vis[x]){update(x);C[x]=y;update(x);}
else C[x]=y;
}
int tmpC[N];
int main()
{
int n,m,Q,i,u,v,op;
n=gi();m=gi();Q=gi();
for(i=1;i<=m;i++)V[i]=gi();
for(i=1;i<=n;i++)W[i]=gi();
for(i=1;i<n;i++){u=gi();v=gi();adde(u,v);}
dfs1(1);top[1]=1;dfs2(1);
for(i=1;i<=n;i++)tmpC[i]=C[i]=gi();
for(i=1;i<=Q;i++){
op=gi();u=gi();v=gi();
if(op==0){
cha[++tcnt][0]=u;
cha[tcnt][1]=v;
cha[tcnt][2]=tmpC[u];
tmpC[u]=v;
}
else{
if(L[u]>L[v])swap(u,v);
int lca=LCA(u,v);
q[++qcnt].l=(lca==u?L[u]:R[u]);
q[qcnt].r=L[v];
q[qcnt].t=tcnt;
q[qcnt].id=qcnt;
}
}
int D=pow(2.0*n,0.6666);
for(i=1;i<=2*n;i++)bel[i]=(i-1)/D+1;
sort(q+1,q+qcnt+1);
int l=1,r=0,t=0;
for(i=1;i<=qcnt;i++){
while(t<q[i].t)t++,modify(cha[t][0],cha[t][1]);
while(t>q[i].t)modify(cha[t][0],cha[t][2]),t--;
while(l>q[i].l)l--,update(pos[l]);
while(r<q[i].r)r++,update(pos[r]);
while(l<q[i].l)update(pos[l]),l++;
while(r>q[i].r)update(pos[r]),r--;
int lca=LCA(pos[q[i].l],pos[q[i].r]);
if(lca!=pos[q[i].l])update(lca);
ans[q[i].id]=sum;
if(lca!=pos[q[i].l])update(lca);
}
for(i=1;i<=qcnt;i++)
printf("%lld\n",ans[i]);
}