CCPC广州补题C. Necklace 代码有问题 有空改一下

针对一个给定的项链分段算法问题,通过二分搜索找到使特定条件成立的最长段最小长度。修正了原有算法中关于偏移量的计算错误,并确保了最终解的正确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Link​​​​​​​

虽然在cf上ac了但评论区指出了我的错误,有空再改2333

题意: 

给出一个有n个珠子的项链,需要分成m段,使得给出的m个数每个数都处在单独一段,输出最长段的最小长度。

1 <= m < n < 1e18, m <= 1e6 保证mi按递增顺序给出

思路: 

显然,二分答案,一开始没有注意是项链,每次check贪心地从0开始,cur表示当前的位置,每一步若cur + mid < a[i],则return false,否则cur = min(cur + mid, a[i+1]-1),wa了。改进的时候加了一个偏移量delta,具体见代码。

一开始的代码虽然过了原题目,但仍然有bug,经评论区大佬指正后修改,然而还是错的

// Decline is inevitable,
// Romance will last forever.
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxm = 1e6 + 10;
#define gc()(is==it?it=(is=in)+fread(in,1,Q,stdin),(is==it?EOF:*is++):*is++)
const int Q=(1<<24)+1;
char in[Q],*is=in,*it=in,c;
void read(long long &n){
  for(n=0;(c=gc())<'0'||c>'9';);
  for(;c<='9'&&c>='0';c=gc())n=n*10+c-48;
}
int n, m;
int a[maxm];
bool ok(int mid) {
    int cur = a[1] - 1; //cur从a[1]的前一位开始 把a[1]看作第1位
    int delta = 0;     //delta表示初始位置最多可以向左(后)移几位
    for(int i = 1; i < m; i++) {//循环m-1次,剩最后一个m不用考虑
                                //因为最后一步一定要和第一步接上,所以其实是确定的
        if(cur + mid < a[i])    //如果够不到下一个,则mid不符合题意,继续二分
            return false;
        //delta = max(delta, mid - (a[i] - cur));  错误代码
        delta = max(delta, mid - (a[i+1] - cur - 1));
        //mid表示能走的步数,括号内表示实际走的步数(只能走到下下个的前一位),差即为delta
        cur = min(cur + mid, a[i+1]-1);//如果够得到下一个,则最多到下下个的前一位
    }
    int cnt = n + a[1] - 1; //相当于把a[1]前的位数补到了尾端
    if(cnt - cur > mid + delta) return false;  //如果最后一步长度大于mid + delta 则false
    return true;
}
void solve() {
    read(n);
    read(m);
    for(int i = 1; i <= m; i++)
        read(a[i]);
    int l = 1, r = n;
    int ans = n;
    while(l <= r) {
        int mid = (l + r) >> 1;
        if(ok(mid)) {
            ans = mid;
            r = mid - 1;
        }
        else l = mid + 1;
    }
    printf("%lld\n", ans);
}
signed main() {
    solve();
    return 0;
}

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值