2022南京icpc区域赛D题讲解

https://codeforces.com/gym/104128/problem/D
要解决这道题目需要使用到二分答案,二分第k大元素值,首先分析如何二分答案的可行性

while (l + 1 < r) {
    //l越大,res越小,能够凑成
    ll mid = (l + r) / 2;
    if (check(mid)>=k)l = mid;
    else r = mid;
}

mid是我们假设的最大的数组中的第k大元素,我们先不考虑选择哪个长为m的子数组并给他对应的元素加上一个排列,我们假设已经通过某些方式得到了已经处理好的数组(最优处理),我们暂且把它称为数组{b},然后很容易知道数组{b}中至少有tmp(tmp用来表示数组中大于等于mid的元素个数)个元素大于等于mid,而最后实际的第k大元素,在数组{b}中刚好有k个元素大于等于第k大元素,这时就可以判断如果tmp>=k说明mid选小了或者刚好相等,因为数组{b}中的每个元素大小是不会变的,你选的mid越小,那么tmp的大小就越大,所以让l=mid,反之如果tmp<k,那么说明选大了,让r=mid.

到此二分的可行性就分析完了,我们该考虑如何才能够在On的时间复杂度内找到这个tmp.接下来我会先把check的代码贴出来来然后逐步分析.

ll n, k, m, c, d;
std::cin >> n >> k >> m >> c >> d;
std::vector<ll>a(n+2);
for (int i = 1; i <= n; i++)std::cin >> a[i];
ll l = -1, r = 1e18;
st
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值