正题
题目链接:https://www.luogu.com.cn/problem/P4074
题目大意
nnn个点的一颗数,第iii个点有一颗cic_ici种类的糖。
第iii次获得jjj种类的糖可以产生价值wi∗vjw_i*v_jwi∗vj。
每次操作
- 修改一个点的糖果种类
- 询问一个路径的价值和
解题思路
用欧拉序可以做到在树上进行莫队,然后带修即可。
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
using namespace std;
const ll N=2e5+10;
struct q_node{ll id,t,l,r;
}q[N];
struct node{ll to,next;
}a[N*2];
ll n,m,Q,T,cnt,tot,answer;
ll v[N],w[N],c[N],ans[N],ls[N];
ll cho[N],cval[N],pre[N];
ll dfn[N],rfn[N],ed[N],ok[N];
ll f[N][21],dep[N],vis[N];
bool operator<(q_node x,q_node y){if(x.l/T!=y.l/T)return x.l/T<y.l/T;if(x.r/T!=y.r/T)return x.r/T<y.r/T;return x.t/T<y.t/T;
}
void addl(ll x,ll y){a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;return;
}
void dfs(ll x,ll fa){dfn[++cnt]=x;rfn[x]=cnt;for(ll i=ls[x];i;i=a[i].next){ll y=a[i].to;if(y==fa)continue;f[y][0]=x;dep[y]=dep[x]+1; dfs(y,x);}dfn[++cnt]=x;ed[x]=cnt;
}
void ycl(){for(ll i=1;i<=20;i++)for(ll j=1;j<=n;j++)f[j][i]=f[f[j][i-1]][i-1];return;
}
ll LCA(ll x,ll y){if(dep[y]>dep[x])swap(x,y);for(ll i=20;i>=0;i--)if(dep[f[x][i]]>=dep[y])x=f[x][i];if(x==y)return x;for(ll i=20;i>=0;i--)if(f[y][i]!=f[x][i])x=f[x][i],y=f[y][i];return f[x][0];
}
void rev(ll x){int k=c[x];if(ok[x])answer-=w[vis[k]]*v[k],vis[k]--;else vis[k]++,answer+=w[vis[k]]*v[k];ok[x]^=1;return;
}
void keep(ll &l,ll &r,ll &t,ll L,ll R,ll T){while(l<L)rev(dfn[l]),l++;while(l>L)l--,rev(dfn[l]);while(r<R)r++,rev(dfn[r]);while(r>R)rev(dfn[r]),r--;while(t<T){t++;ll x=cho[t],flag=0;if(ok[x])rev(x),flag=1;swap(c[x],cval[t]);if(flag)rev(x);}while(t>T){ll x=cho[t],flag=0;if(ok[x])rev(x),flag=1;swap(c[x],cval[t]);if(flag)rev(x);t--;}
}
int main()
{scanf("%lld%lld%lld",&n,&m,&Q);for(ll i=1;i<=m;i++)scanf("%lld",&v[i]);for(ll i=1;i<=n;i++)scanf("%lld",&w[i]);for(ll i=1;i<n;i++){ll x,y;scanf("%lld%lld",&x,&y);addl(x,y);addl(y,x);}for(ll i=1;i<=n;i++)scanf("%lld",&c[i]);dep[1]=1;dfs(1,0);ycl();cnt=tot=0;for(ll i=1;i<=Q;i++){ll op,x,y;scanf("%lld",&op);if(op==0){tot++;scanf("%lld%lld",&cho[tot],&cval[tot]);}else{scanf("%lld%lld",&x,&y);if(rfn[x]>rfn[y])swap(x,y);int lca=LCA(x,y);if(lca==x||lca==y)x=rfn[x],y=rfn[y];else x=ed[x],y=rfn[y];q[++cnt]=(q_node){cnt,tot,x,y};}}T=pow(n,2.0/3);sort(q+1,q+1+cnt);ll l=1,r=0,t=0;for(ll i=1;i<=cnt;i++){ll x=q[i].l,y=q[i].r;keep(l,r,t,x,y,q[i].t);ll lca=LCA(dfn[x],dfn[y]),flag=0;if(dfn[x]!=lca&&dfn[y]!=lca){flag=1;vis[c[lca]]++;answer+=w[vis[c[lca]]]*v[c[lca]];}ans[q[i].id]=answer;if(flag){answer-=w[vis[c[lca]]]*v[c[lca]];vis[c[lca]]--;}}for(ll i=1;i<=cnt;i++)printf("%lld\n",ans[i]);
}