[题解]洛谷P4653

[题解]洛谷P4653

原题链

大体算法

我们可以发现,点亮权值越大的灯泡一定比点亮权值小的灯泡优(显然),所以我们肯定从最大的开始连续地取,那么我们先将权值从大到小排个序,接下来先考虑暴力算法,就是枚举(a)数组取到第(i)位,(b)数组取到第(j)位,并且暴力统计答案,这是我们发现每次统计到第(i)(j)为其实就是(a.b)数组的前缀和,这样我们就可以优化一下,但仍然不是满分
接着我们想,由于最终的答案是取(a.b)两组的最小值,所以如果(a)数组的答案和(b)数组的答案这两个答案差距太大显然是不优的,因为反正是取最小值,所以不如把大的那部分少取一点,花费还更少,其实我们已将正解得出:那就是(a.b)数组的两个答案应该要尽量的接近,所以分两次做,其实也是暴力,第一次从(1~n)枚举(a)数组的前缀和(suma[i]),并用(lower_bound)查询比(suma[i])大的最小的(sumb[j]),并统计答案,再暴力枚举(sumb)即可.

代码

#include <bits/stdc++.h>
using namespace std;
double a[1000010],b[1000010];
double suma[1000010],sumb[1000010];
bool cmp(double x,double y){
	return x > y;
}
int main(){
	freopen("coin.in","r",stdin);
	freopen("coin.out","w",stdout);
	int n;
	scanf("%d",&n);
	for(int i = 1;i <= n;i++)
		cin>>a[i];
	for(int i = 1;i <= n;i++)
		cin>>b[i];
	sort(a + 1,a + n + 1,cmp);sort(b + 1,b + n + 1,cmp);
	suma[1] = a[1];sumb[1] = b[1];
	for(int i = 2;i <= n;i++){
		suma[i] = a[i];
		sumb[i] = b[i];
		suma[i] += suma[i - 1];
		sumb[i] += sumb[i - 1];
	}
	double ans1 = 0.0,ans2 = 0.0;
	for(int i = 1;i <= n;i++){
		int tmp1 = suma[i];
		int p = lower_bound(sumb + 1,sumb + n + 1,tmp1) - sumb;
		ans1 = max(ans1,min(suma[i],sumb[p]) - i - p);
	}
	for(int i = 1;i <= n;i++){
		int tmp1 = sumb[i];
		int p = lower_bound(suma + 1,suma + n + 1,tmp1) - suma;
		ans2 = max(ans2,min(sumb[i],suma[p]) - i - p);
	}
	printf("%.4lf
",max(ans1,ans2));
	return 0;
}
原文地址:https://www.cnblogs.com/czy--blog/p/13916433.html