记录编号 483227 评测结果 AAAAAAAAAA
题目名称 [WC 2013] 糖果公园 最终得分 100
用户昵称 GravatarFoolMike 是否通过 通过
代码语言 C++ 运行时间 12.706 s
提交时间 2018-01-15 19:35:55 内存使用 30.26 MiB
显示代码纯文本
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
int n,m,q_cnt,v[N],w[N],c[N];
int q[N],L[N],R[N],size;
int block_size,now,p[N],fr[N],to[N],cnt_query;
struct query{int l,r,T,lca;}Q[N];
namespace init{
	int e[N],nxt[N],head[N];
	void add(int f,int t){
		static int cnt=0;
		e[++cnt]=t;
		nxt[cnt]=head[f];
		head[f]=cnt;
	}
	int dep[N],dp[18][N];
	void dfs(int x){
		q[L[x]=++size]=x;
		for (int i=head[x];i;i=nxt[i])
		if (!L[e[i]]) dep[e[i]]=dep[x]+1,dp[0][e[i]]=x,dfs(e[i]);
		q[R[x]=++size]=x;
	}
	int lca(int x,int y){
		if (dep[x]<dep[y]) swap(x,y);
		for (int D=dep[x]-dep[y],i=0;i<18;i++)
		if (D>>i&1) x=dp[i][x];
		for (int i=17;i>=0;i--)
		if (dp[i][x]!=dp[i][y]) x=dp[i][x],y=dp[i][y];
		return x==y?x:dp[0][x];
	}
	void init(){
		scanf("%d%d%d",&n,&m,&q_cnt);
		block_size=pow(n,0.67);
		for (int i=1;i<=m;i++) scanf("%d",&v[i]);
		for (int i=1;i<=n;i++) scanf("%d",&w[i]);
		for (int i=1;i<n;i++){
			int u,v;
			scanf("%d%d",&u,&v);
			add(u,v);add(v,u);
		}
		dep[1]=1;dfs(1);
		for (int i=1;i<18;i++)
		for (int j=1;j<=n;j++)
			dp[i][j]=dp[i-1][dp[i-1][j]];
		for (int i=1;i<=n;i++) scanf("%d",&c[i]);
		static int now[N];
		for (int i=1;i<=n;i++) now[i]=c[i];
		for (int i=1;i<=q_cnt;i++){
			int tp,x,y;
			scanf("%d%d%d",&tp,&x,&y);
			if (tp){
				if (L[x]>L[y]) swap(x,y);
				if (R[x]<L[y])
					Q[++cnt_query]=(query){R[x],L[y],i,lca(x,y)};
				else
					Q[++cnt_query]=(query){L[x],L[y],i,0};
			}
			else p[i]=x,fr[i]=now[x],to[i]=now[x]=y;
		}
	}
}
int cnt[N];bool ins[N];ll ans;
bool cmp(query x,query y){
	if (x.l/block_size!=y.l/block_size) return x.l<y.l;
	if (x.r/block_size!=y.r/block_size) return x.r<y.r;
	return x.T<y.T;
}
void insert(int c){ans+=(ll)w[++cnt[c]]*v[c];}
void erase(int c){ans-=(ll)w[cnt[c]--]*v[c];}
void _insert(int x){(ins[x]=!ins[x])?insert(c[x]):erase(c[x]);}
void jump(int T){
	while (now<T){
		++now;
		if (ins[p[now]]) erase(fr[now]),insert(to[now]);
		c[p[now]]=to[now];
	}
	while (now>T){
		if (ins[p[now]]) erase(to[now]),insert(fr[now]);
		c[p[now]]=fr[now];
		now--;
	}
}
ll Ans[N];
int main()
{
	freopen("park.in","r",stdin);
	freopen("park.out","w",stdout);
	init::init();
	sort(Q+1,Q+cnt_query+1,cmp);
	int l=1,r=0;
	for (int i=1;i<=cnt_query;i++){
		int L=Q[i].l,R=Q[i].r;
		while (r<R) _insert(q[++r]);
		while (l>L) _insert(q[--l]);
		while (r>R) _insert(q[r--]);
		while (l<L) _insert(q[l++]);
		if (Q[i].lca) _insert(Q[i].lca);
		jump(Q[i].T);
		Ans[Q[i].T]=ans;
		if (Q[i].lca) _insert(Q[i].lca);
	}
	for (int i=1;i<=q_cnt;i++)
	if (Ans[i]) printf("%lld\n",Ans[i]);
	return 0;
}