您的位置:首页 > 其它

[BZOJ4775][点分树][概率与期望][数学][卡精度]网管

2017-03-25 22:47 447 查看
大小号贡献13次提交……

这题卡精度啊!!有个地方int改成long long就过了

首先,平方的期望不等于期望的平方

E(X2)=DX+E(X)2,DX为X所有情况的方差,为p(1−p)。

在这题中p就是这个节点为黑点的概率

推一推咯

Ans=E((∑x∈Bdist(x,s))2)

A=∑x∈Bdist(x,s)

Ans=DA+E(A)2

E(A)=∑x∈Vpx∗dis(x,s)

DA=D(∑x∈Bdist(x,s))

=∑x∈VD(dis(x,s)[x∈B])

=∑x∈Vdis(x,s)2D(x∈B)

=∑x∈Vdis(x,s)2px∗(1−px)

那么就可以考虑如何在点分树上维护这些东西

考虑当前重心u

E(A)=∑x∈sub(u)px∗(dis(x,u)+dis(u,s))

=∑x∈sub(u)px∗dis(x,u)+dis(u,s)∑x∈sub(u)px

DA=∑x∈sub(u)(dis(x,u)+dis(u,s))2px∗(1−px)

=∑x∈sub(u)dis(x,u)2px(1−px)+2∗dis(u,s)∑x∈sub(u)dis(x,u)px(1−px)+dis(u,s)2∑x∈sub(u)px(1−px)

维护一下这些西格玛就行了

#include <cstdio>
#include <iostream>
#include <algorithm>
#define N 200010
#define eps 1e-10

using namespace std;

typedef pair<double,double> par;

int n,m,Size,Max,cnt;
int vis
,p
,G
,dpt
;
int fa
[25];
double w
,d
,pw
,pd
,A1
,pA1
,A2
,pA2
,A3
,pA3
;
par A
;
struct edge{
int t,nx;
}E[N<<2];

inline void rea(int &x){
char c=getchar(); x=0;
for(;c>'9'||c<'0';c=getchar());
for(;c>='0'&&c<='9';x=x*10+c-'0',c=getchar());
}

inline int LCA(int x,int y){
if(dpt[x]<dpt[y]) return LCA(y,x);
for(int i=20;~i;i--)
if(dpt[fa[x][i]]>=dpt[y]) x=fa[x][i];
if(x==y) return x;
for(int i=20;~i;i--)
if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
return fa[x][0];
}

inline int dis(int x,int y){
return dpt[x]+dpt[y]-2*dpt[LCA(x,y)];
}

void dfs(int x,int f){
fa[x][0]=f; dpt[x]=dpt[f]+1;
for(int i=1;i<=20;i++) fa[x][i]=fa[fa[x][i-1]][i-1];
for(int i=G[x];i;i=E[i].nx)
if(E[i].t!=f) dfs(E[i].t,x);
}

int explore(int x,int f){
int ret=1;
for(int i=G[x];i;i=E[i].nx)
if(E[i].t!=f&&!vis[E[i].t]) ret+=explore(E[i].t,x);
return ret;
}

int Root(int x,int f,int &R){
int S=1,iMax=0;
for(int i=G[x];i;i=E[i].nx)
if(E[i].t!=f&&!vis[E[i].t]){
int k=Root(E[i].t,x,R);
if(k>iMax) iMax=k;
S+=k;
}
if(iMax<Size-S) iMax=Size-S;
if(iMax<Max) Max=iMax,R=x;
return S;
}

void divide(int x,int f){
Size=explore(x,0);
int k; Max=1<<30; Root(x,0,k);
vis[k]=1; p[k]=f;
for(int i=G[k];i;i=E[i].nx)
if(!vis[E[i].t]) divide(E[i].t,k);
}

inline void Insert(int x,int y){
E[++cnt].t=y; E[cnt].nx=G[x]; G[x]=cnt;
E[++cnt].t=x; E[cnt].nx=G[y]; G[y]=cnt;
}

inline void Add(int x){
double y=A[x].first*(1-A[x].first);
w[x]+=A[x].first; A3[x]+=y;
for(int i=x;p[i];i=p[i]){
int D=dis(x,p[i]);
d[p[i]]+=D*A[x].first;
pd[i]+=D*A[x].first;
w[p[i]]+=A[x].first;
pw[i]+=A[x].first;

A1[p[i]]+=D*D*y;
pA1[i]+=D*D*y;
A2[p[i]]+=2*D*y;
pA2[i]+=2*D*y;
A3[p[i]]+=y;
pA3[i]+=y;
}
}

inline void Del(int x){
double y=A[x].first*(1-A[x].first);
w[x]-=A[x].first; A3[x]-=y;
for(int i=x;p[i];i=p[i]){
int D=dis(x,p[i]);
d[p[i]]-=D*A[x].first;
pd[i]-=D*A[x].first;
w[p[i]]-=A[x].first;
pw[i]-=A[x].first;

A1[p[i]]-=D*D*y;
pA1[i]-=D*D*y;
A2[p[i]]-=2*D*y;
pA2[i]-=2*D*y;
A3[p[i]]-=y;
pA3[i]-=y;
}
}

inline void Query(int x){
double Ans1=d[x],Ans2=A1[x];
for(int i=x;p[i];i=p[i]){
long long D=dis(x,p[i]);//!!!
Ans1+=d[p[i]]-pd[i]+D*w[p[i]]-D*pw[i];
Ans2+=A1[p[i]]-pA1[i]+A2[p[i]]*D-pA2[i]*D+D*D*A3[p[i]]-D*D*pA3[i];
}
printf("%.13lf\n",Ans1*Ans1+Ans2);
}

int main(){
freopen("4775.in","r",stdin);
freopen("4775.out","w",stdout);
rea(n); rea(n); rea(m);
for(int i=1;i<=n;i++){
int x; rea(x);
A[i]=par(x,x^1);
}
for(int i=1;i<n;i++){
int x,y; rea(x); rea(y);
Insert(x,y);
}
divide(1,0); dfs(1,0);
for(int i=1;i<=n;i++) Add(i);
while(m--){
int op;rea(op);
if(op&1){
int x,p; rea(x); rea(p);
double k=p/100.0,k1=(100-p)/100.0;
Del(x);
A[x]=par(A[x].second*k+A[x].first*k1,A[x].first*k+A[x].second*k1);
Add(x);
}
else{
int x; rea(x);
Query(x);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: