【CF739E】Gosha is hunting

题意:有n个小精灵,你有a个普通球和b个超级球,用普通球抓住第i只小精灵的概率为$A_i$,用超级球抓住第i只小精灵的概率为$u_i$。你必须一开始就决定向哪些精灵投掷哪些精灵球,同种的球只能对一个精灵用一次,可以对一只精灵投掷两种球,如果两次中有一次抓到则视为抓到。问你如果采用最优的方案,最终抓到小精灵的期望个数是多少。

$n\le 2000$。

题解:我们先将所有小精灵按$B$排序,然后我们枚举最后一个投b或ab的小精灵i,那么不难证明i左边的所有小精灵都是b或a或ab,i右面的小精灵都是0或a。接着我们想把左面的三种情况拆开,不难发现$A_x+B_x-A_xB_x+B_y>B_x+A_y+B_y-A_yB_y$->$(1-B_x)A_x>(1-B_y)A_y$,所以只要将i左边按$(1-B)A$排序,然后就可以枚举j,满足[1,j]都是ab或b,(j,i]都是a或b。此时我们就可以先假设[1,i]全选b,则[1,j]中每个点选ab的贡献就是$A-AB$,(j,i]中每个点选a的贡献就是$A-B$,(i,n]中每个点选a的贡献是$A$。我们只需要用一个数据结构维护前k大值的和即可。用treap比较容易,当然我懒,用的是两个对顶的堆来维护。

时间复杂度$O(n^2\log n)$。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
#define lson x<<1
#define rson x<<1|1
using namespace std;
const int maxn=2010;
int n,A,B;
double ans,sum;
struct node
{
double a,b,c;
}p[maxn];
struct heap
{
priority_queue<double> a,b;
inline double top()
{
while(!b.empty()&&a.top()==b.top()) a.pop(),b.pop();
return a.top();
}
inline int size() {return a.size()-b.size();}
inline void erase(double x) {b.push(x);}
inline void push(double x) {a.push(x);}
inline void pop()
{
while(!b.empty()&&a.top()==b.top()) a.pop(),b.pop();
a.pop();
}
inline void clr()
{
while(!a.empty()) a.pop();
while(!b.empty()) b.pop();
}
};
struct bst
{
heap p1,p2;
int lim;
inline void insert(double x)
{
p1.push(-x),sum+=x;
if(p1.size()>lim) p2.push(-p1.top()),sum+=p1.top(),p1.pop();
}
inline void del(double x)
{
if(x<=p2.top()) p2.erase(x);
else
{
sum-=x,p1.erase(-x);
if(p1.size()<lim&&p2.size()) p1.push(-p2.top()),sum+=p2.top(),p2.pop();
}
}
inline void clr() {p1.clr(),p2.clr();}
}b1,b2;
bool cmp1(const node &a,const node &b)
{
return a.b>b.b;
}
bool cmp2(const node &a,const node &b)
{
return (1-a.a)*a.b>(1-b.a)*b.b;
}
int main()
{
scanf("%d%d%d",&n,&A,&B);
int i,j;
for(i=1;i<=n;i++) scanf("%lf",&p[i].a);
for(i=1;i<=n;i++) scanf("%lf",&p[i].b),p[i].c=1-(1-p[i].a)*(1-p[i].b);
sort(p+1,p+n+1,cmp1);
double sumb=0;
for(i=1;i<B;i++) sumb+=p[i].b;
for(i=B;i<=min(n,A+B);i++)
{
sumb+=p[i].b;
b1.clr(),b2.clr(),b1.lim=A-i+B,b2.lim=i-B,sum=0;
sort(p+1,p+i+1,cmp2);
for(j=1;j<=i;j++) b2.insert(p[j].a-p[j].b);
for(j=i+1;j<=n;j++) b1.insert(p[j].a);
ans=max(ans,sumb+sum);
for(j=1;j<=B;j++)
{
b2.del(p[j].a-p[j].b),b1.insert(p[j].c-p[j].b);
ans=max(ans,sumb+sum);
}
}
printf("%.6lf",ans);
return 0;
}

最新文章

  1. ajax交互方法实现
  2. 【VBS】vbs指定编码保存文本文件(含xml、ini什么的)
  3. Hadoop自定义分组Group
  4. 《DSP using MATLAB》示例Example5.6
  5. 如何让linux定时任务crontab按秒执行
  6. IText&amp;Html2canvas js截图 绘制 导出PDF
  7. mustache.js
  8. js小技巧(二)
  9. Codeforces 219D. Choosing Capital for Treeland (树dp)
  10. php 微信开发之 微信支付 V3 开发 -CURLOP_TIMEOUT问题
  11. poj棋盘分割(记忆化)
  12. centos安装qt开发环境
  13. 树形dp Codeforces Round #364 (Div. 1)B
  14. QEMU KVM Libvirt手册(10): KVM的各种限制
  15. MySQL创建新用户以及ERROR 1396 (HY000)问题解决
  16. python 元组 序列上使用enumerate()函数
  17. Ribbon Status Bar
  18. mysql备份的三种方式
  19. On extracting ops from LLVM backend
  20. leetCode题解之Self Dividing Numbers

热门文章

  1. 使用 SharpSvn 执行 svn 操作的Demo
  2. linux如何通过脚本来修改用户的密码?脚本自动化修改用户密码?
  3. 一致性Hash算法原理及C#代码实现
  4. jdbc数据访问技术
  5. 使用powerdesigner连接MySQL并设置逆向工程图文教程
  6. Oracle sqlldr导入之“MAXIMUM ERROR COUNT EXCEEDED”
  7. java 对 汉字排序(按照拼音字母排序)
  8. PHP MYSQL 分表方法
  9. x64枚举DPC定时器
  10. 树莓派3安装opencv2程序无法运行