【CF739E】Gosha is hunting 贪心

【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;
}

原文地址:https://www.cnblogs.com/CQzhangyu/p/8503737.html

时间: 2024-10-01 22:37:46

【CF739E】Gosha is hunting 贪心的相关文章

cf739E Gosha is hunting (flows)

739E 有$a$个普通球,$b$个超级球,有$n$个要捕捉的宝可梦,对于第$i$个宝可梦普通球的捕捉概率是$p_i$,超级球的捕捉概率是$u_i$,每种球只能扔一个到同一个宝可梦,同一个宝可梦可以被扔两种球.然后问在最优策略下捕捉个数的期望 考虑概率$dp$,发现状态无法简化到$n^2$级别,原来不是dp 假定每个宝可梦只能被扔一个球,那就是个匹配问题了,设$A$为普通球,$B$为超级球,源点向$A$,$B$连容量为球的个数,花费为$0$的边,$A,B$分别向每个精灵连容量为$1$,花费为$p

CF739E Gosha is hunting 【WQS二分 + 期望】

题目链接 CF739E 题解 抓住个数的期望即为概率之和 使用\(A\)的期望为\(p[i]\) 使用\(B\)的期望为\(u[i]\) 都使用的期望为\(p[i] + u[i] - u[i]p[i]\) 当然是用越多越好 但是他很烦地给了个上限,我们就需要作出选择了 有一个很明显的\(O(n^3)\)的\(dp\),显然过不了 但我们有一个很好的\(WQS\)二分 我们非常想去掉这个上限 那就去掉吧,但是每用一次都要付出一个代价 我们二分这个代价,当使用次数恰好为为\(a\)和\(b\)时就是

CF739E Gosha is hunting(费用流,期望)

根据期望的线性性答案就是捕捉每一只精灵的概率之和. 捕捉一只精灵的方案如下: 1.使用一个\(A\)精灵球,贡献为\(A[i]\) 2.使用一个\(B\)精灵球,贡献为\(B[i]\) 3.使用一个\(A\)精灵球和一个\(B\)精灵球,贡献为\(A[i]+B[i]-A[i]*B[i]\) 然后我们可以这样建图: 源点\(S\)向两个精灵球连容量为精灵球数量,费用为\(0\)的边. \(A\)精灵球向i连容量为\(1\),费用为\(A[i]\)的边. \(B\)精灵球向i连容量为\(1\),费用

CF739E Gosha is hunting DP+wqs二分

我是从其他博客里看到这题的,上面说做法是wqs二分套wqs二分?但是我好懒呀,只用了一个wqs二分,于是\(O(nlog^2n)\)→\(O(n^2logn)\) 首先我们有一个\(O(n^3)\)的暴力\(DP\),转移好写,形式优美,但复杂度不对 该怎样发现它的凸性质呢 1.打表√ 2.冷静分析一波,每一种球肯定是越多越好,于是我们先固定选择\(a\)个普通球,然后那\(b\)个大师球肯定是从大到小挑选.这样的话每多选一个,新增的收益就会下降一点,也就是说这是个上凸函数.(口胡如果假的话,就

CF739E Gosha is hunting

法一: 匹配问题,网络流! 最大费用最大流,S到A,B流a/b费0,A,B到i流1费p[i]/u[i],同时选择再减p[i]*u[i]? 连二次!所以i到T流1费0流1费-p[i]*u[i] 最大流由于ab都选择完最优 最大费用,所以不会第一次走-p[i]*u[i] 法二: DP怎么写? dp[i][j][k] 优化? 一定选择a.b个! 恰好选择a.b个? WQS二分! 一定是满足凸函数的性质的 所以选择若干个a,代价ca,求dp[i][b] 再次WQS二分! 所以选择若干个a,b,代价ca,

【CF739E】Gosha is hunting(WQS二分套WQS二分)

点此看题面 大致题意: 你有两种捕捉球(分别为\(A\)个和\(B\)个),要捕捉\(n\)个神奇宝贝,第\(i\)个神奇宝贝被第一种球捕捉的概率是\(s1_i\),被第二种球捕捉的概率是\(s2_i\),问在最优策略下期望捕捉到的神奇宝贝数量. \(WQS\)二分 这应该是一道比较经典的\(WQS\)二分题(毕竟是 \(WQS\)二分套\(WQS\)二分). \(WQS\)二分套\(WQS\)二分 如果你知道\(WQS\)二分,应该就不难想到\(WQS\)二分一个代价\(C1\),表示每使用一

Codeforces739E Gosha is hunting

题意:现在有n个精灵,两种精灵球各m1和m2个,每个精灵单独使用第一种精灵球有pi的概率被捕获,单独使用第二种精灵球有ui的概率被捕获,同时使用有1-(1-pi)*(1-ui)的概率被捕获.一种精灵球在一个精灵身上只能用一次,但你可以在一个精灵上用两种精灵球.求最优策略下期望获得精灵的只数. 如果一只精灵上不能同时用两种精灵球,那么就是一个显然的费用流建图,点A表示第一种精灵球,点B表示第二种精灵球,源点向A,B各连一条流量等于对应精灵球数目的边(费用为0),A,B分别向每个精灵连一条流量为1,

Codeforces.739E.Gosha is hunting(DP 带权二分)

题目链接 \(Description\) 有n只精灵,两种精灵球,每种球能捕捉到第i只精灵的概率已知.求用A个低级球和B个高级球能捕捉到精灵数的最大期望. \(Solution\) 设f[i][a][b]表示前i只用了a个低级球,b个高级球的最大期望.转移时四种情况显然.复杂度\(\mathcal O(nAB)\). 随着某种球可使用数的增多,f应是凸函数,即增长越来越慢.而且两种球都满足这个性质. 于是可以wqs二分套wqs二分了..没有个数限制取个max记一下个数就可以了.复杂度\(\mat

【uva 1615】Highway(算法效率--贪心 区间选点问题)

题意:给定平面上N个点和一个值D,要求在x轴上选出尽量少的点,使得对于给定的每个店,都有一个选出的点离它的欧几里德距离不超过D. 解法:先把问题转换成模型,把对平面的点满足条件的点在x轴的直线上可得到一个个区间,这样就是选最小的点覆盖所有的区间的问题了.我之前的一篇博文有较详细的解释:关于贪心算法的经典问题(算法效率 or 动态规划).代码实现我先空着.挖坑~