Codeforces 494C - Helping People
题意
有一个长度为 \(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\) 。因此有转移
\]
代码
#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的更多相关文章
- [Codeforces-div.1 494C] Helping People
[Codeforces-div.1 494C] Helping People 试题分析 不难注意到题目所给的性质是一棵树,所以肯定是树形dp. 那么期望没有办法合并,我们还有一种最笨的方法就是求出概率 ...
- CodeForces 1105E Helping Hiasat 最大独立集
Helping Hiasat 题解: 如果我们把连续的2出现的人都相互连边的话, 题目就是问最大独立集的答案是多少. 求最大独立集可以将图变成反图, 然后求最大团. 代码: #include<b ...
- 【Codeforces 1105E】Helping Hiasat
Codeforces 1105 E 题意:给你m个事件,每个事件可能是以下两种之一: \(1\),代表此时可以更改用户名 \(2\) \(s\),代表\(s\)来查看是否用户名与其名字相符 一共有\( ...
- Codeforces Round #533 (Div. 2) E - Helping Hiasat 最大团
E - Helping Hiasat 裸的最大团,写了一种 2 ^ (m / 2) * (m / 2)的复杂度的壮压, 应该还有更好的方法. #include<bits/stdc++.h> ...
- 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 ...
- Codeforces Round #533 (Div. 2) E. Helping Hiasat(最大独立集)
题目链接:https://codeforces.com/contest/1105/problem/E 题意:有 n 个事件,op = 1 表示我可以修改昵称,op = 2 表示一个名为 s_i 的朋友 ...
- Solution -「CF 494C」Helping People
\(\mathcal{Description}\) Link. 给定序列 \(\{a_n\}\) 和 \(m\) 个操作,第 \(i\) 个操作有 \(p_i\) 的概率将 \([l_i,r_ ...
- Codeforces Round #802 (Div. 2)C. Helping the Nature(差分)
题目链接 题目大意: 给你一个有n个元素的数组a,你可以通过一下三种操作使数组的每一个值都为0: 选择一个下标i,然后让a[1],a[2]....a[ i ] 都减一; 选择一个下标i,然后让a[i] ...
- 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 ...
随机推荐
- 处女男学Android(七)---Android 应用资源之StateListDrawable
前言 本篇Blog将记录关于Android应用资源中最经常使用的一个Drawable资源--StateListDrawable,本来说应当继续写UI方面的内容,突然跳到应用资源这边,主要是由于之前写界 ...
- MIPI Alliance (MIPI联盟)
一.介绍 1.MIPI联盟,即移动产业处理器接口(Mobile Industry Processor Interface 简称MIPI)联盟.MIPI(移动产业处理器接口)是MIPI联盟发起的为移动应 ...
- 使用redis
通过 Nuget获取包StackExchange.Redis 写数据: ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(&quo ...
- Microsoft Tech Summit 2017
Microsoft Tech Summit 2017 时间:2017.10.31-2017.11.3 地点:北京国际饭店会议中心
- Python算法基础
一.简介 定义和特征 定义:算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制.也就是说,能够对一定规范的输入,在有限时 ...
- 20155238 2016-2017-2 《JAVA程序设计》第十周学习总结
教材学习内容总结 # Java计算机网络基础 计算机网络 计算机网络是通过传输介质.通信设施和网络通信协议,把分散在不同地点的计算机设备互连起来,实现资源共享和数据传输的系统.网络编程就就是编写程序使 ...
- Luogu P3370 【模板】字符串哈希
方法很多,hash,双hash(个人想到一种三hash),挂链,还有STL: map 乱搞 CODE #include<iostream> #include<map> #inc ...
- PowerBI开发 第八篇:查询参数
在PowerBI Desktop中,用户可以定义一个或多个查询参数(Query Parameter),参数的功能是为了实现PowerBI的参数化编程,使得Data Source的属性.替换值和过滤数据 ...
- 利用fiddler core api 拦截修改 websocket 数据
一般的中间人攻击基本都是拦截修改普通的http协议里面的内容,而对于怎么拦截修改websocket协议传输的内容好像都没有多少介绍. talk is cheap show me the code us ...
- 浅谈iOS 自动调节文本高度
文字展示是任何GUI开发的一个最常规的编程任务.可能一提及文字我们脑中想到的无非就是 Label 和 Text 这两个关键词,今天我们就谈谈 Label. 无论在 Windows 或者 Web 开发中 ...