题意

有一个长度为 \(n\) 的数列 \(a\),有 \(m\) 个 操作,每个操作是给 \(a[l_i,r_i]\) 中的数都加一,一个操作有 \(p_i\) 的概率执行(否则不执行)。一个性质是任意两个区间不相交或完全包含(可重叠)。问执行完所有操作后 \(a\) 中最大值的期望。

\(n\le 10^5,m\le 5000,a\le 10^9\) 。

分析

想象一下多个不相交或完全包含的区间,他们的结构其实是一棵树。外层为父亲,内层为儿子。

要计算的是最大值的期望,而这个最大值是由多个操作得到的,所以无法分别计算期望再合并。解决这个问题的方法是先算出概率,再得到期望。

到最后,一个区间 \([l,r]\) 的最大值只可能是 \([mx,mx+q]\) 中的数(\(mx\) 为原序列中这个区间的最大值)。那么那么我们可以用这个东西来 dp。

设 \(f[x][j]\) 表示 \(x\) 点子树中的操作结束后,\(x\) 点表示的这个区间的最大值小于等于 \(mx_x+j\) 的概率。这样设计是因为若是等于的话,计算的时候转移还是要求前缀和,相当于是小于等于了。若 \(x\) 这个操作不执行,那么从子树 \(v\) 转移,子树 \(v\) 需要让其最后的区间最大值小于等于 \(mx_x+j\) ;若执行,那么子树的需要让其区间最大值小于等于 \(mx_i+j-1\) 。因此有转移

\[f[x][j]=p_x\prod f[v][mx_x+j-1-mx_v]+(1-p_x)\prod f[v][mx_x+j-mx_v]
\]

代码

#include<bits/stdc++.h>
using namespace std;
const int maxq=5e3+5;
const int maxm=1e4+5;
const int maxn=1e5+1;
int n,a[maxn],m,M,mx;
inline void Max(int &x,int y) {x=max(x,y);}
struct Q {
int l,r,mx;
double p;
inline bool operator < (const Q &b) const {return l!=b.l?l<b.l:r>b.r;}
} q[maxq];
namespace rmq {
const int maxj=17;
int f[maxn][maxj],bin[maxn];
void build() {
for (int i=2;i<=n;++i) bin[i]=bin[i>>1]+1;
for (int i=1;i<=n;++i) f[i][0]=a[i];
for (int j=1;j<maxj;++j) for (int i=1;i<=n;++i) {
int x=i+(1<<(j-1));
f[i][j]=f[i][j-1];
if (x<=n && f[x][j-1]>f[i][j]) f[i][j]=f[x][j-1];
}
}
inline int query(int l,int r) {
int x=bin[r-l+1];
return max(f[l][x],f[r-(1<<x)+1][x]);
}
}
namespace tree {
vector<int> g[maxq];
double f[maxq][maxm];
inline void add(int x,int y) {g[x].push_back(y);}
void build() {
sort(q+1,q+m+1);
static int sta[maxq],top;
q[sta[top=0]=0]=(Q){1,n,min(mx,m),0};
for (int i=1;i<=m;++i) {
Q &p=q[i];
for (;top>0 && p.l>q[sta[top]].r;--top) add(sta[top-1],sta[top]);
sta[++top]=i;
}
for (;top;--top) add(sta[top-1],sta[top]);
}
void dfs(int x) {
if (g[x].empty()) {
f[x][0]=1-q[x].p;
for (int i=1;i<=M;++i) f[x][i]=1;
return;
}
for (const int &v:g[x]) dfs(v);
for (int j=0;j<=m;++j) {
double fir=j?q[x].p:0,sec=1-q[x].p;
for (const int &v:g[x]) {
int the=q[x].mx-q[v].mx+j;
fir*=f[v][the-1];
sec*=f[v][the];
}
f[x][j]=fir+sec;
}
for (int j=m+1;j<=M;++j) f[x][j]=f[x][j-1];
}
double calc() {
double ret=mx;
for (int i=1;i<=m;++i) ret+=(f[0][i]-f[0][i-1])*i;
return ret;
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
#endif
scanf("%d%d",&n,&m),M=m<<1;
for (int i=1;i<=n;++i) {
scanf("%d",a+i);
Max(mx,a[i]);
}
if (mx>m) for (int i=1;i<=n;++i) a[i]=max(0,a[i]+m-mx);
rmq::build();
for (int i=1;i<=m;++i) {
scanf("%d%d%lf",&q[i].l,&q[i].r,&q[i].p);
q[i].mx=rmq::query(q[i].l,q[i].r);
}
tree::build();
tree::dfs(0);
double ans=tree::calc();
printf("%.10lf\n",ans);
return 0;
}

Codeforces 494C - Helping People的更多相关文章

  1. [Codeforces-div.1 494C] Helping People

    [Codeforces-div.1 494C] Helping People 试题分析 不难注意到题目所给的性质是一棵树,所以肯定是树形dp. 那么期望没有办法合并,我们还有一种最笨的方法就是求出概率 ...

  2. CodeForces 1105E Helping Hiasat 最大独立集

    Helping Hiasat 题解: 如果我们把连续的2出现的人都相互连边的话, 题目就是问最大独立集的答案是多少. 求最大独立集可以将图变成反图, 然后求最大团. 代码: #include<b ...

  3. 【Codeforces 1105E】Helping Hiasat

    Codeforces 1105 E 题意:给你m个事件,每个事件可能是以下两种之一: \(1\),代表此时可以更改用户名 \(2\) \(s\),代表\(s\)来查看是否用户名与其名字相符 一共有\( ...

  4. Codeforces Round #533 (Div. 2) E - Helping Hiasat 最大团

    E - Helping Hiasat 裸的最大团,写了一种 2 ^ (m / 2)  * (m / 2)的复杂度的壮压, 应该还有更好的方法. #include<bits/stdc++.h> ...

  5. Codeforces #282 div 1 C Helping People 题解

    CF 282 C Helping People 题解 [原题] time limit per test 2 seconds memory limit per test 512 megabytes in ...

  6. Codeforces Round #533 (Div. 2) E. Helping Hiasat(最大独立集)

    题目链接:https://codeforces.com/contest/1105/problem/E 题意:有 n 个事件,op = 1 表示我可以修改昵称,op = 2 表示一个名为 s_i 的朋友 ...

  7. Solution -「CF 494C」Helping People

    \(\mathcal{Description}\)   Link.   给定序列 \(\{a_n\}\) 和 \(m\) 个操作,第 \(i\) 个操作有 \(p_i\) 的概率将 \([l_i,r_ ...

  8. Codeforces Round #802 (Div. 2)C. Helping the Nature(差分)

    题目链接 题目大意: 给你一个有n个元素的数组a,你可以通过一下三种操作使数组的每一个值都为0: 选择一个下标i,然后让a[1],a[2]....a[ i ] 都减一; 选择一个下标i,然后让a[i] ...

  9. Codeforces Round #439 (Div. 2) Problem E (Codeforces 869E) - 暴力 - 随机化 - 二维树状数组 - 差分

    Adieu l'ami. Koyomi is helping Oshino, an acquaintance of his, to take care of an open space around ...

随机推荐

  1. Python2.7-anydbm

    anydbm模块,把各种数据库模块(dbhash (requires bsddb), gdbm, or dbm)的接口进行了统一.打开后返回的对象操作和字典类似 模块方法: anydbm.open(f ...

  2. 搭建windows远程节点_jmeter自动化测试环境(接口测试)

    WINDOWS10系统下 环境 172.16.0.115虚拟机windows系统作为远程节点. jenkins安装在172.16.0.119:8088虚拟机中. 一.安装配置Java环境   wind ...

  3. 【转】为什么volatile不能保证原子性而Atomic可以?

    直接上好文链接!!! 为什么volatile不能保证原子性而Atomic可以?

  4. DQN(Deep Reiforcement Learning) 发展历程(五)

    目录 值函数的近似 DQN Nature DQN DDQN Prioritized Replay DQN Dueling DQN 参考 DQN发展历程(一) DQN发展历程(二) DQN发展历程(三) ...

  5. 20155220 Exp2 后门原理与实践

    20155220 Exp2 后门原理与实践 1.Windows获得Linux Shell 在windows下,打开CMD,使用ipconfig指令查看本机IP 然后使用ncat.exe程序,ncat. ...

  6. [2016北京集训测试赛17]crash的游戏-[组合数+斯特林数+拉格朗日插值]

    Description Solution 核心思想是把组合数当成一个奇怪的多项式,然后拉格朗日插值..:哦对了,还要用到第二类斯特林数(就是把若干个球放到若干个盒子)的一个公式: $x^{n}=\su ...

  7. 阿里云OSS不同账号之间的迁移

    目录 一.需求说明 二.Ossimport概述 三.配置运行环境 1.配置jdk环境 2.部署方式 3.下载并部署ossimport 四.修改单机Job的配置文件local_job.cfg 五.执行迁 ...

  8. python删除文件与目录的方法

    python内置方法删除目录(空目录与非空目录)及文件 1.os.remove(file_path):删除文件 #PPTV是文件夹,xen.txt是文件 >>> os.remove( ...

  9. mybatis源码-解析配置文件(二)之解析的流程

    目录 1. 简介 2. 配置文件解析流程分析 2.1 调用 2.2 解析的目的 2.3 XML 解析流程 2.3.1 build(parser) 2.3.2 new XMLConfigBuilder( ...

  10. yocto-sumo源码解析(五): bitbake/lib/bb/main.py

    续前面分析,就该对bitbake_main()这个函数进行分析了,这个函数位于bitbake/lib/bb/main.py. 1. 检测主机操作系统是否为linux并且/dev/shm是否存在,pyt ...