Present

Present

https://ac.nowcoder.com/acm/problem/110615

Present

题目大意:

先给你一串序列,你至多有次操作使得一段长度为的区间加一
问这串序列的最小值最大可以是多少?

分析:

最小值最大或者最大值最小,我们的第一反应可能都是二分答案

简单证明一下:

如果最小值最大为,那么只要我们少做一次操作,那么也是可行的
这满足二分答案的性质,所以呢二分答案没有问题的

那么关于函数的话,如果当前我们枚举到的数他小于这个我们的值,那么我们就给这一段区间加上这个差值(如果可以加,否则返回零)
那么时间复杂度大概就是,可以接受的

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const ll maxn = 1e5 + 10;
const ll mod = 1e9 + 7;

inline ll __read()
{
    ll x(0), t(1);
    char o (getchar());
    while (o < '0' || o > '9') {
        if (o == '-') t = -1;
        o = getchar();
    }
    for (; o >= '0' && o <= '9'; o = getchar()) x = (x << 1) + (x << 3) + (o ^ 48);
    return x * t;
}

ll n, m, w, a[maxn];
ll CF[maxn], temp[maxn];
ll l(0x7fffffff), r, ans;

inline bool Check(ll x) 
{
    memcpy(temp + 1, CF + 1, sizeof(ll) * n);
    ll now(0), rest(m);
    for (ll i = 1; i <= n; ++i) {
        now += temp[i];
        if (now >= x) continue;
        if (now + rest < x) return 0;
        ll get = x - now;
        rest -= get;
        now += get;
        if (i + w <= n) temp[i + w] -= get;
    }
    return 1;
}

signed main()
{
    n = __read(), m = __read(), w = __read();
    for (ll i = 1; i <= n; ++i)  {
        a[i] = __read();
        CF[i] = a[i] - a[i - 1];
        l = min(l, a[i]), r = max(r, a[i]);
    }
    r += m;
    while (l <= r) {
        ll mid = (l + r) >> 1;
        if (Check(mid)) ans = mid, l = mid + 1;
        else r = mid - 1;
    }
    printf ("%lld\n", ans);
    system("pause");
}
有的没的 文章被收录于专栏

RT,有的没的

全部评论

相关推荐

野猪不是猪🐗:现在的环境就是这样,供远大于求。 以前卡学历,现在最高学历不够卡了,还要卡第一学历。 还是不够筛,于是还要求得有实习、不能有gap等等... 可能这个岗位总共就一个hc,筛到最后还是有十几个人满足这些要求。他们都非常优秀,各方面都很棒。 那没办法了,看那个顺眼选哪个呗。 很残酷,也很现实
点赞 评论 收藏
分享
04-17 10:16
门头沟学院 Java
小浪_coder:24届很难找了,马上25的都毕业了还有很多没找到的
点赞 评论 收藏
分享
评论
3
4
分享

创作者周榜

更多
牛客网
牛客企业服务