bzoj3052: [wc2013]糖果公园

Posted wangyurzee

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3052: [wc2013]糖果公园相关的知识,希望对你有一定的参考价值。

又是一代神题。

uoj测速rank10,bzoj测速rank26(截止当前2016.5.30 12:58)

带修改的树上莫队。

修改很少,块的大小随便定都能A

然而我一开始把开3次根写成了pow(blabla,1/3)

我一副见了鬼的样子.jpg

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#define ll long long
#define N 200005
#define M 200005

using namespace std;
inline int read(){
	int ret=0;char ch=getchar();
	while (ch<‘0‘||ch>‘9‘) ch=getchar();
	while (‘0‘<=ch&&ch<=‘9‘){
		ret=ret*10-48+ch;
		ch=getchar();
	}
	return ret;
}

struct edge{
	int adj,next;
	edge(){}
	edge(int _adj,int _next):adj(_adj),next(_next){}
} e[M];
int n,g[N],m;
void AddEdge(int u,int v){
	e[++m]=edge(v,g[u]);g[u]=m;
	e[++m]=edge(u,g[v]);g[v]=m;
}
int fa[N],deep[N],dfn[N],stamp;
void dfs(int u){
	dfn[u]=++stamp;
	deep[u]=deep[fa[u]]+1;
	for (int i=g[u];i;i=e[i].next){
		int v=e[i].adj;
		if (v==fa[u]) continue;
		fa[v]=u;
		dfs(v);
	}
	++stamp;
}
int anc[N][19];
void precompute(){
	fa[1]=fa[0]=deep[0]=0;stamp=0;
	dfs(1);
	memset(anc[0],0,sizeof(anc[0]));
	for (int i=1;i<=n;++i) anc[i][0]=fa[i];
	for (int k=1;k<17;++k)
		for (int i=1;i<=n;++i)
			anc[i][k]=anc[anc[i][k-1]][k-1];
}
int qlca(int u,int v){
	if (deep[u]<deep[v]) swap(u,v);
	for (int k=16;k>=0;--k) if (deep[anc[u][k]]>=deep[v]) u=anc[u][k];
	for (int k=16;k>=0;--k) if (anc[u][k]!=anc[v][k]) u=anc[u][k],v=anc[v][k];
	return u==v?u:fa[u];
}

struct Query{
	int u,v,tm,id;
} q[N];
int bl[N];
inline bool operator <(const Query &x,const Query &y){
	if (bl[dfn[x.u]]!=bl[dfn[y.u]]) return bl[dfn[x.u]]<bl[dfn[y.u]];
	else if (bl[dfn[x.v]]!=bl[dfn[y.v]]) return bl[dfn[x.v]]<bl[dfn[y.v]];
	else return ((x.tm<y.tm)^(bl[dfn[x.v]]&1));
}
int Q;


int cdy,c[N],val[N],kk[N];
int cnt[N];
bool exist[N];
ll nowans;
void change(int u){
	if (exist[u]) nowans-=(ll)val[c[u]]*kk[cnt[c[u]]--];
	else nowans+=(ll)val[c[u]]*kk[++cnt[c[u]]];
	exist[u]^=1;
}
void moveTo(int u,int v){
	int w=qlca(u,v);
	for (;u!=w;u=fa[u]) change(u);
	for (;v!=w;v=fa[v]) change(v);
}
void modify(int u,int to){
	if (exist[u]) nowans-=(ll)val[c[u]]*kk[cnt[c[u]]--];
	c[u]=to;
	if (exist[u]) nowans+=(ll)val[c[u]]*kk[++cnt[c[u]]];
}

int mdf,pt[N],fr[N],to[N];
int tmpc[N];
ll ans[N];
int main(){
//	freopen("candyland.in","r",stdin);
//	freopen("candyland.out","w",stdout);
	n=read();cdy=read();Q=read();
	for (int i=1;i<=cdy;++i) val[i]=read();
	for (int i=1;i<=n;++i) kk[i]=read();
	memset(g,0,sizeof(g));m=1;
	for (int i=1;i<n;++i) AddEdge(read(),read());
	for (int i=1;i<=n;++i) tmpc[i]=c[i]=read();
	precompute();
	mdf=0;
	for (int i=1;i<=Q;++i)if (read()){
		q[i].u=read();q[i].v=read();
		if (dfn[q[i].u]>dfn[q[i].v]) swap(q[i].u,q[i].v);
		q[i].tm=mdf;
		q[i].id=i;
	}
	else{
		--Q;--i;++mdf;
		pt[mdf]=read();
		fr[mdf]=c[pt[mdf]];
		to[mdf]=c[pt[mdf]]=read();
	}
	int K=max(sqrt(n),pow((double)4*n*n*mdf/Q,1.0/3));
	for (int i=1;i<=2*n;++i) bl[i]=i/K;
	sort(q+1,q+Q+1);
	for (int i=1;i<=n;++i) c[i]=tmpc[i];
	memset(cnt,0,sizeof(cnt));
	memset(exist,0,sizeof(exist));
	q[0].u=q[0].v=1;q[0].tm=0;
	nowans=0;
	int nowtm=0,w;
	for (int i=1;i<=Q;++i){
		moveTo(q[i-1].u,q[i].u);
		moveTo(q[i-1].v,q[i].v);
		change(w=qlca(q[i].u,q[i].v));
		for (;nowtm<q[i].tm;++nowtm) modify(pt[nowtm+1],to[nowtm+1]);
		for (;nowtm>q[i].tm;--nowtm) modify(pt[nowtm],fr[nowtm]);
		ans[q[i].id]=nowans;
		change(w);
	}

	for (int i=1;i<=Q;++i) printf("%lld\n",ans[i]);
	return 0;
}

  

以上是关于bzoj3052: [wc2013]糖果公园的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 3052: [wc2013]糖果公园 | 树上莫队

BZOJ3052 WC2013 糖果公园

bzoj3052: [wc2013]糖果公园

BZOJ3052: [wc2013]糖果公园 树分块+待修改莫队算法

bzoj3052: [wc2013]糖果公园

BZOJ3052 & UOJ58:WC2013糖果公园——题解