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

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;
}

猜你喜欢

转载自blog.csdn.net/m0_59273843/article/details/121369072
今日推荐