1. 程式人生 > 其它 >[四校聯考]約會

[四校聯考]約會

羊駝非常喜歡菠蘿,他們雖然身處異地(即他們不會處在同一個樹節點上),但經常到某地約會。 他們所處的世界是一棵以1為根的樹,這棵樹上的每個節點都有一個權值Wi,並且他們約會時會到他們各自所在節點的最近公共祖先(lca)上,假設他們分別處於x節點和y節點,他們的花費的代價就是Wx+Wy,有時某個節點的權值會加上某個數,有時某個節點的子樹都會加上某個數。 現在他們向你尋求幫助,他想知道當他們約會的地點為z(即lca為z時),求他們花費的期望代價。

Description

羊駝非常喜歡菠蘿,他們雖然身處異地(即他們不會處在同一個樹節點上),但經常到某地約會。 他們所處的世界是一棵以1為根的樹,這棵樹上的每個節點都有一個權值Wi,並且他們約會時會到他們各自所在節點的最近公共祖先(lca)上,假設他們分別處於x節點和y節點,他們的花費的代價就是\(W_x+W_y\),有時某個節點的權值會改加上某個數,有時某個節點的子樹都會加上某個數。 現在他們向你尋求幫助,他想知道當他們約會的地點為z(即lca為z時),求他們花費的期望代價。

Input

第一行輸入一個整數n,m,n是節點個數,m是操作總數。
第二行讀入n-1個整數\(f_i\),表示2-n節點的父親。
第三行讀入n個整數\(s_i\)

,表示n個節點一開始的權值。
接下來m行,一共有三種操作。
“S x s”節點x的權值加上s。
“M x s”節點x的子樹(包括自己本身)每個節點都加上s。
“Q x”查詢他們約會的地點為z(即lca為z)時,求花費的期望代價。

Output

對於每一個Q輸出一個實數ans,絕對誤差在\(10^{-4}\)以內就視為正確。

Sample Input

5 4
1 1 1 1
1 2 2 3 3
Q 1
S 1 4
M 1 -2
Q 1

Sample Output

4.400000
2.000000

HINT

\(n,m\leq300000,-10^5\leq{s}\leq10^5\).

Solution

\(u\) 為根的子樹對父親 \(f\)

的貢獻為\(\sum{s_i}\times{siz[f]-siz[u]}\).

對樹進行輕重鏈剖分,對於每個詢問,\(\sum\varDelta{s_i}\)是固定的.

除了\(x\)之外,其他改變的貢獻均為\(\sum\varDelta{s_i}\times{siz[f]-siz[u]}\)

對於輕鏈直接暴力修改,重鏈線段樹維護 \(siz[f]-siz[son[f]]\) 及相關值即可.

#define N 300005
#define M 3000005
typedef long long ll;
struct graph{
	int nxt,to;
}e[N];
ll s[N],tot[N],ans[N];
int dep[N],siz[N],son[N],top[N];
int g[N],f[N],w[N],p[N],n,m,cnt;
inline void addedge(int x,int y){
	e[++cnt].nxt=g[x];g[x]=cnt;e[cnt].to=y;
}
inline void dfs1(int u){
	int mx=0;siz[u]=1;
	for(int i=g[u],c;i;i=e[i].nxt){
		f[c=e[i].to]=u;
		dep[c]=dep[u]+1;dfs1(c);
		siz[u]+=siz[c];
		if(siz[c]>mx){
			mx=siz[c];son[u]=c;
		}
	}
}
inline void dfs2(int u,int tp){
	int c;
	tot[u]=1ll*(siz[u]-1);
	ans[u]=1ll*s[u]*(siz[u]-1);
	p[u]=++cnt;w[cnt]=u;top[u]=tp;
	if(c=son[u]){
		dfs2(son[u],tp);
		s[u]+=s[c];
		ans[u]+=1ll*s[c]*(siz[u]-siz[c]);
		tot[u]+=1ll*(siz[u]-siz[c])*siz[c];
	}
	for(int i=g[u];i;i=e[i].nxt)
		if((c=e[i].to)!=son[u]) {
			dfs2(c,c);
			s[u]+=s[c];
			ans[u]+=1ll*s[c]*(siz[u]-siz[c]);
			tot[u]+=1ll*(siz[u]-siz[c])*siz[c];
		}
	tot[u]>>=1;
}
struct SegMent{
	int l,r;ll sum/*ans*/,lzy/**/,lzt/*tot[u]<<1*/;
}lt[M];
inline void build(int u,int l,int r){
	lt[u].l=l;lt[u].r=r;
	if(lt[u].l<lt[u].r){
		int lef=u<<1,rig=u<<1|1;
		int mid=(lt[u].l+lt[u].r)>>1;
		build(lef,l,mid);build(rig,mid+1,r);
	}
	else{
		int p=w[lt[u].l];
		lt[u].sum=ans[p];
	}
}
inline void pushdown(int u){
	if(!lt[u].lzy&&!lt[u].lzt) return;
	if(lt[u].l<lt[u].r){
		int lef=u<<1,rig=u<<1|1;ll s;
		s=lt[u].lzy;lt[lef].lzy+=s;lt[rig].lzy+=s;
		s=lt[u].lzt;lt[lef].lzt+=s;lt[rig].lzt+=s;
	}
	else{
		ll s=lt[u].lzy;int p=w[lt[u].l];
		lt[u].sum+=1ll*(siz[p]-siz[son[p]])*s;
		s=lt[u].lzt;lt[u].sum+=1ll*(tot[p]<<1ll)*s;
	}
	lt[u].lzy=lt[u].lzt=0;
}
inline void add_s(int u,int l,int r,ll s){
	if(lt[u].l>=l&&lt[u].r<=r){
		lt[u].lzy+=s;return;
	}
	if(lt[u].l<lt[u].r){
		int lef=u<<1,rig=u<<1|1;
		int mid=(lt[u].l+lt[u].r)>>1;
		if(l<=mid) add_s(lef,l,r,s);
		if(r>mid) add_s(rig,l,r,s);
	}
}
inline void add_t(int u,int l,int r,ll s){
	if(lt[u].l>=l&&lt[u].r<=r){
		lt[u].lzt+=s;return;
	}
	if(lt[u].l<lt[u].r){
		int lef=u<<1,rig=u<<1|1;
		int mid=(lt[u].l+lt[u].r)>>1;
		if(l<=mid) add_t(lef,l,r,s);
		if(r>mid) add_t(rig,l,r,s);
	}
}
inline void add(int u,int x,ll s){
	pushdown(u);
	if(lt[u].l==lt[u].r){
		lt[u].sum+=s;return;
	}
	if(lt[u].l<lt[u].r){
		int lef=u<<1,rig=u<<1|1;
		int mid=(lt[u].l+lt[u].r)>>1;
		if(x<=mid) add(lef,x,s);
		else add(rig,x,s);
	}
}
inline ll ask(int u,int x){
	pushdown(u);
	if(lt[u].l==lt[u].r)
		return lt[u].sum;
	if(lt[u].l<lt[u].r){
		int lef=u<<1,rig=u<<1|1;
		int mid=(lt[u].l+lt[u].r)>>1;
		if(x<=mid) return ask(lef,x);
		return ask(rig,x);
	}
}
inline void change(int u,int lst,ll s){
	if(!u) return;
	if(lst==top[lst]){
		add(1,p[u],1ll*s*(siz[u]-siz[lst]));
		if(p[top[u]]<p[u])
			add_s(1,p[top[u]],p[u]-1,s);
	}
	else add_s(1,p[top[u]],p[u],s);
	lst=top[u];u=f[top[u]];
	while(u){
		add(1,p[u],1ll*s*(siz[u]-siz[lst]));
		if(p[top[u]]<p[u])
			add_s(1,p[top[u]],p[u]-1,s);
		lst=top[u];u=f[top[u]];
	}
}
inline void Aireen(){
	n=read();m=read();
	for(int i=2;i<=n;++i) addedge(read(),i);
	for(int i=1;i<=n;++i) s[i]=1ll*read();
	dep[1]=1;dfs1(1);
	cnt=0;dfs2(1,1);build(1,1,n);
	char c[2];int x,s;
	while(m--){
		scanf("%s",&c);x=read();
		if(c[0]=='S') s=read(),add(1,p[x],1ll*(siz[x]-1)*s),change(f[x],x,1ll*s);
		else if(c[0]=='M') s=read(),add_t(1,p[x],p[x]+siz[x]-1,s),change(f[x],x,1ll*s*siz[x]);
		else printf("%lf\n",(double)(ask(1,p[x]))/(double)(tot[x]));
	}
}

2017-04-20 19:53:21