The 2021 CCPC Guangzhou Onsite C. Necklace

Problem - C - Codeforces

二分+贪心的题

二分很简单,主要是怎么贪。我的方法是从如图1号节点开始,尽可能向右贪心,如果max_len超出了,就把项链整体往左移动,这样可以保证利用到的max_len最大,也就是尽可能减少浪费。

由于必须保证每段项链都包含恰好一个美丽宝石,所以项链是无法无限地整体向左移动的。用move记录能向左移动的最大距离,每次分段时都要更新。

最后要判断一下第一段项链和最后一段项链能不能连接上

 代码如下

#include <bits/stdc++.h>
using namespace std;

#define int long long
//#define go(i, a, b) for (int i = a; i <= b; ++i)
//#define com(i, a, b) for (int i = a; i >= b; --i)
#define mem(a, b) memset(a, b, sizeof(a))
#define fo(i, a) for (int i = 0; i < a; ++i)

const int N = 1e6 + 10;

int n, m, a[N];

bool check(int mlen) {
    int move, pos, res = 0;
    move = n * 2;
    pos = a[1] - 1;
    for (int i = 2; i <= m; ++i) {
        if (pos + mlen < a[i - 1]) return 0;
        int nxtp = a[i] - pos - 1;
        if (mlen > nxtp) {
            int dis = min(move, mlen - nxtp);
            move -= dis;
            res += dis;
            pos = a[i] - 1;
        } else {
            pos = pos + mlen;
        }
        move = min(move, pos - a[i - 1]);
    }
    if (n - pos + a[1] - 1 - res <= mlen)
        return 1;
    else
        return 0;
}

void read(int &x) {
    int f = 1;
    char c;
    c = getchar();
    x = 0;
    while (!isdigit(c)) {
        if (c == '-') f = -1;
        c = getchar();
    }
    while (isdigit(c)) {
        x = x * 10 + c - '0';
        c = getchar();
    }
    x *= f;
}

signed main() {
    //freopen("input.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
    cin >> n >> m;
    for (int i = 1; i <= m; ++i) {
        read(a[i]);
    }
    int l = 1, r = n;
    while (l <= r) {
        int mid = l + r >> 1;
        if (check(mid))
            r = mid - 1;
        else
            l = mid + 1;
    }
    cout << r + 1 << endl;
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值