[题解]洛谷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\n",max(ans1,ans2));
return 0;
}