ICPC南京站 D - Chat Program 二分+差分

 第K大的数>=mid  等效于  有超过k个>=mid的数

//二分+差分
#include <bits/stdc++.h>
using namespace std;
#define go(i, a, b) for (int i = a; i <= b; ++i)
#define int long long

const int N = 2e5 + 10;

int n, k, m, c, d;
int a[N], cf[N];

bool check(int mid) {
    memset(cf, 0, sizeof(cf));
    go(i, 1, n) {
        if (a[i] >= mid) {//本来就大于mid
            cf[1]++;
        } else {
            int l = max(i - m + 1, 1ll);
            if (a[i] + c + (i - l) * d < mid) continue;//如果加上等差数列仍不可能大于Mid就无需考虑
            int j;
            if (d == 0)//特判公差为0的情况
                j = 0;
            else
                j = (mid - a[i] - c - 1) / d + 1;//向上整除计算j
            j = max(j, 0ll);//要求j>=0
            int r = i - j;//r为右边界位置
            ++cf[l];
            --cf[r + 1];//差分计算
        }
    }
    go(i, 1, n) cf[i] += cf[i - 1];

    int ans = 0;
    go(i, 1, n) ans = max(ans, cf[i]);

    return ans >= k;
}

signed main() {
    // freopen("input.txt", "r", stdin);
    //  freopen("out.txt", "w", stdout);
    cin >> n >> k >> m >> c >> d;
    go(i, 1, n) scanf("%lld", &a[i]);
    int l = 0, r = 1e16;//最大值为a[i]+c+(m-1)*d,所以上限尽可能大,会超Int
    while (l <= r) {
        int mid = l + r >> 1;
        // cout << mid << endl;
        if (check(mid)) {
            l = mid + 1;
        } else
            r = mid - 1;
    }
    cout << l - 1;
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值