标签:复杂度 head names iostream one sizeof sed lap ||
树上莫队模板题,树上莫队计算贡献后是除去 $u,v$ 的 $lca$ 的,简单用前缀和维护即可。
因为是待修莫队,块大小为 $n^{\frac{2}{3}}$ 时最小,时间复杂度 $O(n^{\frac{5}{3}})$ 。
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<cmath> #define LL long long using namespace std; inline int read(){ int f=1,ans=0;char c=getchar(); while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();} while(c>=‘0‘&&c<=‘9‘){ans=ans*10+c-‘0‘;c=getchar();} return f*ans; } const int MAXN=100001; struct node{ int u,v,nex; }x[MAXN<<1]; int cnt,head[MAXN]; LL S[MAXN]; void add(int u,int v){ x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++; } int n,m,q,sta[MAXN],blo,bl[MAXN],tot,fa[MAXN][21],dep[MAXN],col[MAXN]; LL w[MAXN]; inline void dfs(int u,int fath){ int now=sta[0]; fa[u][0]=fath,dep[u]=dep[fath]+1; for(int i=1;(1<<i)<=dep[u];i++) fa[u][i]=fa[fa[u][i-1]][i-1]; for(int i=head[u];i!=-1;i=x[i].nex){ if(x[i].v==fath) continue; dfs(x[i].v,u); if(sta[0]-now>=blo){ tot++; while(sta[0]!=now) bl[sta[sta[0]]]=tot,sta[0]--; } }sta[++sta[0]]=u;return; } inline int lca(int u,int v){ if(dep[u]<dep[v]) swap(u,v); for(int i=18;i>=0;i--) if(dep[u]-(1<<i)>=dep[v]) u=fa[u][i]; if(u==v) return u; for(int i=18;i>=0;i--){ if(fa[u][i]==fa[v][i]) continue; u=fa[u][i],v=fa[v][i]; }return fa[u][0]; } int Col[MAXN]; struct Query{ int x,y,T,idx,idy,id; LL ans; }query[MAXN]; struct Change{ int x,now,las; }change[MAXN]; bool cmp(Query x1,Query x2){ if(x1.idx==x2.idx){ if(x1.idy==x2.idy) return x1.T<x2.T; return x1.idy<x2.idy; }return x1.idx<x2.idx; } bool cmp1(Query x1,Query x2){ return x1.id<x2.id; } int totq,totc,vis[MAXN]; LL Ans,Cnt[MAXN]; inline void Add(int u){ Ans-=S[Cnt[col[u]]]*w[col[u]]; Cnt[col[u]]++; Ans+=S[Cnt[col[u]]]*w[col[u]];return; } inline void del(int u){ Ans-=S[Cnt[col[u]]]*w[col[u]]; Cnt[col[u]]--; Ans+=S[Cnt[col[u]]]*w[col[u]];return; } inline void Run(int u){ if(vis[u]){del(u),vis[u]=0;return;} else{Add(u);vis[u]=1;return;} } inline void Modify(int u,int w){ if(vis[u]){ del(u); col[u]=w; Add(u); } col[u]=w;return; } inline void move(int u,int v){ if(dep[u]<dep[v]) swap(u,v); while(dep[u]>dep[v]) Run(u),u=fa[u][0]; while(u!=v) Run(u),Run(v),u=fa[u][0],v=fa[v][0]; return; } inline void solve(){ int u=1,v=1,T=0; for(register int i=1;i<=totq;i++){ while(T<query[i].T) Modify(change[T+1].x,change[T+1].now),T++; while(T>query[i].T) Modify(change[T].x,change[T].las),T--; move(u,query[i].x),u=query[i].x; move(v,query[i].y),v=query[i].y; int Lca=lca(u,v); Run(Lca),query[i].ans=Ans,Run(Lca); }return; } signed main(){ // freopen("1.in","r",stdin); memset(head,-1,sizeof(head)); n=read(),m=read(),q=read();blo=pow(n,0.45); for(register int i=1;i<=m;i++) w[i]=read(); for(register int i=1;i<=n;i++) S[i]=S[i-1]+read(); for(register int i=1;i<n;i++){ int u=read(),v=read(); add(u,v),add(v,u); } dfs(1,0); while(sta[0]) bl[sta[sta[0]]]=tot,sta[0]--; for(register int i=1;i<=n;i++) Col[i]=col[i]=read(); while(q--){ int opt=read(); if(opt==1){ int x=read(),y=read(); ++totq; query[totq].x=x,query[totq].y=y,query[totq].T=totc,query[totq].idx=bl[x],query[totq].idy=bl[y]; query[totq].id=totq; }else{ ++totc; int x=read(),co=read(); change[totc].x=x,change[totc].las=Col[x],change[totc].now=Col[x]=co; } } sort(query+1,query+totq+1,cmp); solve(); sort(query+1,query+totq+1,cmp1); for(register int i=1;i<=totq;i++) printf("%lld\n",query[i].ans);return 0; }
标签:复杂度 head names iostream one sizeof sed lap ||
原文地址:https://www.cnblogs.com/si-rui-yang/p/11260322.html