1. 程式人生 > >bzoj3052 [wc2013]糖果公園(樹上莫隊,帶修改)

bzoj3052 [wc2013]糖果公園(樹上莫隊,帶修改)

樹上莫隊參見spoj_cot2,帶修改莫隊參見bzoj2120.這道題就是把這倆和在一起了╭(╯^╰)╮。bzoj上時間很寬鬆。。大家如果沒把握還是不要去爆oj了的好。給大家推薦個好地方UOJ,這題的題號是58。可以先在那過了再說。。uoj的評測機好好的說。。順便我樹上莫隊也是從建了uoj的vfk那裡學來的。。大家可以去搜一下他的部落格。我在這裡放連結是不是算侵權??不懂。。只能orz神犇。(因為打錯變數調了一下午的我,欲哭無淚。辣雞樣例,打錯變數都能過。。)

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define ll long long
#define N 100005
using namespace std;
int n,m,qq,block,a[N],h[N],num=0,now=0,prev[N];
int fa[N][18],dep[N],stack[N],top=0,dfn_num=0,dfn[N];
int f[N],Log[N],tot=0,block_num=0,belong[N];
ll w[N],ans=0,ANS[N],v[N];
bool vis[N];
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return x*f;
}
inline int swap(int &x,int &y){x^=y;y^=x;x^=y;}
struct edge{
	int to,next;
}data[N<<1];
struct timeflow{
	int pre,to,pos;
}modify[N];
struct query{
	int l,r,id,timen;
}q[N];
inline int cmp(query x,query y){
	if(belong[x.l]==belong[y.l]){
		return dfn[x.r]==dfn[y.r]?x.timen<y.timen:dfn[x.r]<dfn[y.r];
	}else return belong[x.l]<belong[y.l];
}
inline int dfs(int x){
	dfn[x]=++dfn_num;int size=0;
	for(int i=1;i<=Log[dep[x]];++i)
		fa[x][i]=fa[fa[x][i-1]][i-1];
	for(int i=h[x];i;i=data[i].next){
		int y=data[i].to;
		if(y==fa[x][0]) continue;
		fa[y][0]=x;dep[y]=dep[x]+1;
		size+=dfs(y);
		if(size>=block){
			++block_num;
			while(size--) belong[stack[top--]]=block_num;
		}
	}
	stack[++top]=x;
	return size+1;
}
inline void change(int x,int y){
	if(vis[x]){
		ans-=w[f[a[x]]]*v[a[x]];f[a[x]]--;
		a[x]=y;
		f[a[x]]++;ans+=w[f[a[x]]]*v[a[x]];
	}
	else a[x]=y;
}
inline int lca(int x,int y){
	if(dep[x]<dep[y]) swap(x,y);
	int d=dep[x]-dep[y];
	for(int i=0;i<=Log[d];++i)
		if(d&(1<<i)) x=fa[x][i];
	if(x==y) return x;
	for(int i=Log[n];i>=0;--i) 
		if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
	return fa[x][0];
}
inline void reverse(int x){
	if(vis[x]) ans-=w[f[a[x]]]*v[a[x]],f[a[x]]--;
	else f[a[x]]++,ans+=w[f[a[x]]]*v[a[x]];
	vis[x]^=1;
}
inline void solve(int x,int y){
	while(x!=y){
		if(dep[x]>dep[y]) reverse(x),x=fa[x][0];
		else reverse(y),y=fa[y][0];
	}
}
int main(){
//	freopen("a.in","r",stdin);
	n=read();m=read();qq=read();block=pow(n,2.0/3)*0.5;
	for(int i=1;i<=m;++i) v[i]=read();
	for(int i=1;i<=n;++i) w[i]=read();
	for(int i=1;i<n;++i){
		int x=read(),y=read();
		data[++num].to=y;data[num].next=h[x];h[x]=num;
		data[++num].to=x;data[num].next=h[y];h[y]=num;
	}
	for(int i=1;i<=n;++i) prev[i]=a[i]=read();
	Log[0]=-1;for(int i=1;i<=n;++i) Log[i]=Log[i>>1]+1;
	dep[1]=1;dfs(1);++block_num;
	while(top) belong[stack[top--]]=block_num;
	while(qq--){
		int op=read(),x=read(),y=read();
		if(!op){
			modify[++now].pre=prev[x];prev[x]=y;
			modify[now].to=y;modify[now].pos=x;
		}
		else{
			q[++tot].l=x;q[tot].r=y;q[tot].timen=now;q[tot].id=tot;
			if(belong[x]>belong[y]) swap(q[tot].l,q[tot].r);
		}
	}sort(q+1,q+tot+1,cmp);
	for(int i=1;i<=q[1].timen;++i) a[modify[i].pos]=modify[i].to;
	solve(q[1].l,q[1].r);int t=lca(q[1].l,q[1].r);
	ANS[q[1].id]=ans+v[a[t]]*(w[f[a[t]]+1]);
	for(int i=2;i<=tot;++i){
		for(int j=q[i-1].timen;j>q[i].timen;--j) change(modify[j].pos,modify[j].pre);
		for(int j=q[i-1].timen;j<q[i].timen;++j) change(modify[j+1].pos,modify[j+1].to);
		solve(q[i-1].l,q[i].l);solve(q[i-1].r,q[i].r);
		int t=lca(q[i].l,q[i].r);ANS[q[i].id]=ans+v[a[t]]*(w[f[a[t]]+1]);
	}
	for(int i=1;i<=tot;++i) printf("%lld\n",ANS[i]);
	return 0;
}