題解
首先我們發現喫糖的順序是不會影響答案的
影響答案的是每種糖的個數
所以我們可以直接利用樹上莫隊來做
樹上莫隊有兩種寫法,一種是在括號序列上進行莫隊,另一種就直接對樹進行分塊,在樹上進行莫隊
這裏寫的是在括號序列上的莫隊
如何帶修改呢
我們維護一種有三個指針的莫隊(比普通的莫隊多一個時間指針)
類似普通的莫隊一樣移動指針就可以了
只不過塊的大小要調爲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]);
}