小题
一句话题意:给两个长为 的 数组 , ,定义收益: 数组中选 个数放前面, 数组中选 个数放前面,收益为 。求最大收益。
做法: 说用三分做,但我只会贪心。我们把 都从大到小排序,分别求前缀和。显然的是我们从大到小选一定是最优的。首先我们想枚举 ,表示 数组分别选到第几个,算答案。但是就 了。我们发现,如果我选的 刚好比 小(或等),那么如果我再把 数组往后选一个,肯定是在做无用功。因此我们只需考虑两边和相当的情况,即对每个位置在另一个数组中找lower_bound。一个细节是,要用总和更小的数组去找另一个。(玄学)
其实最开始是这样想的:从大到小排好序后,直接用两个指针扫两边,贪心找和更小的一边。这样做和上述做法本质一样,但不知道为什么 一直 ......
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
const double eps = 1e-6;
int n;
double a[N], b[N], sma[N], smb[N];
double res;
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; ++i) scanf("%lf%lf", &a[i], &b[i]);
sort(a + 1, a + n + 1); sort(b + 1, b + n + 1);
for(int i = n; i; --i)
{
sma[n - i + 1] = sma[n - i] + a[i];
smb[n - i + 1] = smb[n - i] + b[i];
}
if(smb[n] < sma[n])
{
swap(a, b);
swap(sma, smb);
}
int p;
for(int i = 1; i <= n; ++i)
{
p = lower_bound(smb + 1, smb + n + 1, sma[i]) - smb;
res = max(res, max(sma[i] - i - p, smb[p - 1] - i - p + 1));
}
printf("%.4lf", res);
return 0;
}
//后一种WA点的做法
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int n;
double a[N], b[N];
double res;
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; ++i) scanf("%lf%lf", &a[i], &b[i]);
sort(a + 1, a + n + 1); sort(b + 1, b + n + 1);
int p1 = n, p2 = n;
double x = 0, y = 0;
while(p1 && p2)
{
if(x <= y)
x += a[p1--];
else
y += b[p2--];
--x; --y;
res = max(res, min(x, y));
}
printf("%.4lf", res);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具