2021CCPC廣州站C. Necklace


題目:C. Necklace

題意:

https://codeforces.com/gym/103415/problem/C

​ 長度為 n 的項鏈上有 m 個珠子,每個珠子分一段,問最長段長度的最小值

思路:二分+貪心

​ 每次check貪心地從第一個位置開始,所以一開始偏移量最大為:n-a[m]+a[1]-1,mi表示當前起始位置最大的偏移量,每經過一段區間mi要取最小值,不然最開始位置偏移會超過他所在的區間,cnt記錄最開始的起始位置一共最大往前的偏移量

代碼:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int long long
const int mod=998244353;
const int N=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;
int n,m;
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 a[N];
bool check(int x){
	int mi=n-a[m]+a[1]-1;//當前起始位置最大的偏移量
	int mm=mi;
	int now=0;//用來記錄后面一段需要補充前面一段的大小
	int cnt=0;//記錄最開始的起始位置一共最大往前的偏移量
	for(int i=1;i<m;i++){
		int xx=x-now;//x-減去要給上一段分配的值表示還能給當前區間分配的值
		int cha=a[i+1]-a[i];//當前段的大小
		if(xx<=0) return false;//不能再分給后面的區間了就不合法 
		if(cha>xx){
			now=a[i+1]-(a[i]+xx);
			mi = min(mi, xx - 1);
		}
		else{
			now=0;
			int m1=min(mi,xx-cha);
			cnt+=m1;
			mi=min(mi-m1,cha-1);
		}
	}
	int ans=now+mm+1-x;//還需要給前面段多少個加上現在這段需要多少個-x=當前段需要分到多少個偏移量
	if(x-now>=mm+1||cnt>=ans) return true;//能給最后一段區間分的值>大於最后一段區間大小或者總的能偏移的量>=還需要偏移的量
	return false;

}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	read(n),read(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;
		else l=mid+1;
	}
	printf("%lld\n", l);
	return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM