[WC2013] 糖果公园
Posted si-rui-yang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[WC2013] 糖果公园相关的知识,希望对你有一定的参考价值。
$solution:$
树上莫队模板题,树上莫队计算贡献后是除去 $u,v$ 的 $lca$ 的,简单用前缀和维护即可。
因为是待修莫队,块大小为 $n^\frac23$ 时最小,时间复杂度 $O(n^\frac53)$ 。
#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; elseAdd(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;
以上是关于[WC2013] 糖果公园的主要内容,如果未能解决你的问题,请参考以下文章