2018.09.27 codeforces1045D. Interstellar battle(期望dp)
2024-09-24 17:42:02
传送门
一道有意思的期望dp。
题意是给出一棵树,每个点最开始都有一个gg的概率,有m次修改,每次修改会把某个点gg的概率更换掉,让你求出每次修改之后整个树被分成的连通块的数量的期望(gg掉的点不算)。
%%%%dzyo神仙。
考虑每个点对答案的贡献。
一个点对答案有贡献当且仅当它的父亲gg且它自己没有gg。
于是这样所有加起来就是一次询问的答案。
接着考虑如何解决多次询问。
每次修改一个点的点权,只会影响它的儿子与父亲对答案的贡献。
因此我们直接维护一个sum数组表示所有儿子不gg的期望之和。
这样修改就很方便了。
代码:
#include<bits/stdc++.h>
#define N 100005
using namespace std;
double P[N],sum[N],ans=0;
int n,q,first[N],cnt=0,fa[N];
struct edge{int v,next;}e[N<<1];
inline void add(int u,int v){e[++cnt].v=v,e[cnt].next=first[u],first[u]=cnt;}
inline void dfs(int p){
ans+=P[fa[p]]*(1-P[p]);
for(int i=first[p];i;i=e[i].next){
int v=e[i].v;
if(v==fa[p])continue;
fa[v]=p,dfs(v),sum[p]+=1-P[v];
}
}
inline int read(){
int ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
int main(){
n=read(),P[0]=1;
for(int i=1;i<=n;++i)scanf("%lf",&P[i]);
for(int i=1;i<n;++i){
int u=read()+1,v=read()+1;
add(u,v),add(v,u);
}
dfs(1),q=read();
while(q--){
int a=read()+1;
double b;
scanf("%lf",&b);
ans-=P[a]*sum[a]+P[fa[a]]*(1-P[a]),sum[fa[a]]-=1-P[a];
P[a]=b;
ans+=P[a]*sum[a]+P[fa[a]]*(1-P[a]),sum[fa[a]]+=1-P[a];
printf("%.5lf\n",ans);
}
return 0;
}
最新文章
- 在Eclipse中对包进行增删改查
- ognl
- Caused by: java.lang.UnsatisfiedLinkError...解决经历
- iOS 定制controller过渡动画 ViewController Custom Transition使用体会
- java简单优化和编写规范,自己总结的。
- CentOS 7.0系统安装配置图解教程
- 【转】android蓝牙开发 蓝牙设备的查找和连接
- Linux学习之nfs安装配置
- JUnit4教程-高速入口
- Win10无法连接远程桌面提示“你的凭据不工作”的三个解决方法
- Java开发笔记(五)数值变量的类型
- web plugins
- 升级到 .NET Core 2.1
- 整理一下pywinauto 的sendeys(py2.7)换成python3.6用PyUserInput
- mysql5.6以上版本: timestamp current_timestamp报1064/1067错误
- CSS3 过渡动画
- Ubuntu访问Windows共享目录
- Java实现Kmeans算法
- Atomic原子操作原理剖析
- Spring Boot实现多个数据源教程收集(待实践)