CF2272C Yet Another Black Cell Problem 题解
很显然这个东西具有单调性,考虑二分这个 check 它是否合法。
首先对于黑点
否则,如果它左右的黑点都距离自己太远,只能新开一个黑点(题目里可以任选至多
得到一堆区间,我们计算出最少的黑点数,使得任何一个区间里都至少有一个黑点。
考虑怎么贪心做这个东西。很简单,因为区间长度固定,直接按照右端点(左端点也是一个意思)升序排序,然后扫一遍整个区间。如果上一个新黑点还包含在这个区间内,就直接借用一下,不开新的;否则,因为后续其他区间都比这个区间靠后,所以我们贪心选择该区间的右端点作为新黑点。统计个数并判断是否
CF tag 里有 dp,不知道哪里来的。
注意二分的范围为
::::success[code && submission]
#include<bits/stdc++.h>
#define LL long long
#define UInt unsigned int
#define ULL unsigned long long
#define LD long double
#define pii pair<int,int>
#define pLL pair<LL,LL>
#define pDD pair<LD,LD>
#define fr first
#define se second
#define pb push_back
#define isr insert
#define _i128 __int128
using namespace std;
const int N = 2e5+5;
const LL INF = 1e9+1099;
struct node{LL l,r;}p[N];
LL T,n,cnt,a[N],l,r,Ans;
LL read(){
LL su=0,pp=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')pp=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){su=su*10+ch-'0';ch=getchar();}
return su*pp;
}
bool cmp(node d1,node d2){return d1.r<d2.r;}
bool check(LL k){
int tot=0;
for(int i=1;i<=n;i++){
bool flag=1;
if(i>1&&a[i]-a[i-1]<=k)flag=0;
if(i<n&&a[i+1]-a[i]<=k)flag=0;
if(flag)p[++tot]={a[i]-k,a[i]+k};
}
int hav=0;LL now=0;
for(int i=1;i<=tot;i++)
if(i==1||now<p[i].l)++hav,now=p[i].r;
return (hav<=cnt);
}
int main(){
T=read();
while(T--){
n=read(),cnt=read();
for(int i=1;i<=n;i++)a[i]=read();
l=1,r=INF,Ans=INF;
while(l<=r){
LL mid=(l+r)>>1;
if(check(mid))Ans=mid,r=mid-1;
else l=mid+1;
}
cout<<Ans<<"\n";
}
return 0;
}
::::
如果本篇题解对你有帮助的话,麻烦你点一个小小的赞,真是太感谢啦!