[SP32952] ADAFTBLL - Ada and Football
前置:莫队。
先用树上莫队转换成序列,修改则最后套个带修莫队。
假设新到一个点,它的权值已经出现了 \(apr\) 次。
那答案加上 \(apr\) 就行(前后贡献相减得出的)。
/* BORROWED_CODE */
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=2e5+10;
#define LL long long
int s[N],t,n,m,len,hd[N],lg[N],id,f[N][25],fi[N],la[N],d[N],a[N];
int qc,up_t;LL ans[N],res,cnt[N];bool vs[N];
struct edge{int v,nex;}e[N];void add_e(int u,int v){e[++id].v=v;e[id].nex=hd[u];hd[u]=id;}
struct query{int l,r,lc,tm,id;}q[N];
struct update{int p,v;}c[N];
bool cmp(query a,query b){
if(a.l/len!=b.l/len)return a.l/len<b.l/len;
if(a.r/len!=b.r/len)return a.r/len<b.r/len;
return a.tm<b.tm;
}
void dfs(int u,int fa_p){
fi[u]=++t;s[t]=u;
d[u]=d[fa_p]+1;f[u][0]=fa_p;
for(int i=1;i<=lg[d[u]];++i)f[u][i]=f[f[u][i-1]][i-1];
for(int i=hd[u];i;i=e[i].nex)if(e[i].v!=fa_p)dfs(e[i].v,u);
la[u]=++t;s[t]=u;
}
int lca(int x,int y){
if(d[x]<d[y])swap(x,y);
while(d[x]>d[y])x=f[x][lg[d[x]-d[y]]-1];
if(x==y)return x;
for(int i=lg[d[x]];i>=0;--i)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
return f[x][0];
}
void upd(int x){
vs[x]^=1;
res-=cnt[a[x]]*(cnt[a[x]]-1ll)/2;
cnt[a[x]]+=vs[x]?1:-1;
res+=cnt[a[x]]*(cnt[a[x]]-1ll)/2;
}
int main(){
scanf("%d%d",&n,&m);len=pow(n,2.0/3);for(int i=1;i<=n;++i)scanf("%d",&a[i]);
for(int u,v,i=1;i<n;++i)scanf("%d%d",&u,&v),u++,v++,add_e(u,v),add_e(v,u);
for(int i=1;i<N;++i)lg[i]=lg[i-1]+((1<<lg[i-1])==i);dfs(1,0);
for(int op,x,y,i=1;i<=m;++i){
scanf("%d%d%d",&op,&x,&y);
if(op==1)c[++up_t]={x+1,y};
else{
qc++;x++;y++;if(fi[x]>fi[y])swap(x,y);int z=lca(x,y);
if(z!=x)q[qc]={la[x],fi[y],z,up_t,qc};
else q[qc]={fi[x],fi[y],0,up_t,qc};
}
}
m=qc;sort(q+1,q+m+1,cmp);
for(int i=0,j=1,ct=0,k=1;k<=m;++k){
int l=q[k].l,r=q[k].r,tm=q[k].tm,lc=q[k].lc;
while(i<r)upd(s[++i]);
while(i>r)upd(s[i--]);
while(j>l)upd(s[--j]);
while(j<l)upd(s[j++]);
if(lc)upd(lc);
while(ct<tm){
ct++;int p=c[ct].p;
if(vs[p]){
res-=cnt[a[p]]*(cnt[a[p]]-1ll)/2;
cnt[a[p]]--;
res+=cnt[a[p]]*(cnt[a[p]]-1ll)/2;
res-=cnt[c[ct].v]*(cnt[c[ct].v]-1ll)/2;
cnt[c[ct].v]++;
res+=cnt[c[ct].v]*(cnt[c[ct].v]-1ll)/2;
}
swap(a[p],c[ct].v);
}
while(ct>tm){
int p=c[ct].p;
if(vs[p]){
res-=cnt[a[p]]*(cnt[a[p]]-1ll)/2;
cnt[a[p]]--;
res+=cnt[a[p]]*(cnt[a[p]]-1ll)/2;
res-=cnt[c[ct].v]*(cnt[c[ct].v]-1ll)/2;
cnt[c[ct].v]++;
res+=cnt[c[ct].v]*(cnt[c[ct].v]-1ll)/2;
}
swap(a[p],c[ct].v);
ct--;
}
ans[q[k].id]=res;
if(lc)upd(lc);
}
for(int i=1;i<=m;++i)printf("%lld\n",ans[i]);
return 0;
}
/* BORROWED_CODE */

浙公网安备 33010602011771号