把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

题解 CF1729D

题目链接 CF1729D


题意

有长度为 n 的数组 xy ,可以选择若干个下标,将选择的下标分成若干组(每组最少 2 个),使每组中下标对应的 x 之和不大于 y 之和。问最大的组数。


分析

因为每次都是选择对应的 xiyi,
那么不妨再写一个数组 fi , fi=yixi 。 对于成立的每一组, f 之和大于 0 。 所以每一组必有一个 f >=0

结论 1 :长度都为 2。

证明:
对于长度大于 2 的每一组,一定可以将其中 f<0 的全部不选,一定可以将其中多余的 f>=0 的不选。
因此,对于最终组数最多情况,必然存在每一组长度都为 2 的情况。

结论2 : 每一组的 f 要么是都 >=0 , 或者有一个 <0

证明显然。

结论3 :对于每一个 f>=0 的下标,能选择 f<0 的就不让其选择 f>=0 的。

因为要使组数最大,因此显然。


如此我们就有了代码的思路:
先对 f 进行排序,并标记排序后第一个 f>=0 的下标。
对于这个 f
判断与我们现在没有选择的最大负值 f 相加是否大于等于 0 ,
否则将其下一个 f 与之组成一组。


AC 代码

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+5;
int n, m;
int a[N];
int T;
signed main() {
cin>>T;
while(T--) {
cin>>n;
for(int i=1; i<=n; ++i) {
cin>>a[i];
}
for(int j=1; j<=n; ++j) {
int x;
cin>>x;
a[j]=x-a[j];
}
sort(a+1,a+n+1);
int l=0;
for(int i=1; i<=n; ++i ) {
if(a[i]<0) l=i;
else break;
}
int cnt=0;
for(int i=l+1; i<=n; ++i) {
if(l!=0&&a[i]+a[l]>=0) cnt++,l--;
else {
++i;
if(i<=n)
cnt++;
}
}
cout<<cnt<<endl;;
}
return 0;
}
posted @   djh0314  阅读(6)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
浏览器标题切换
浏览器标题切换end
点击右上角即可分享
微信分享提示