120561D

https://ac.nowcoder.com/acm/contest/120561/D

赛时想到了二分,但是没想好的检验策略。赛后看好像上ST表也能做,但是太麻烦了就不写了。

后面补题的时候尝试自己再想想,发现思维难度还是有的。主要是想复杂了,当时想的是维护跳一步能到的最远距离,以及在自己到最远距离之间一步跳的最远的点。事实上写下来就是很复杂,一堆细节,还容易TLE。后面看了正解做法,只需要维护:在自己左边及自己的所有点中,能跳的最远的距离是多少。因为每个点都要染色,所以一定从左往右,这样做一定不劣。这样就很好实现了。

代码:

#include<bits/stdc++.h>
using namespace std;
int n,k,a[10001000],bg,ne[1000100];
int read(){
	char ch=getchar();int x=0,f=1;
	while(ch<'0'||ch>'9'){
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch<='9'&&ch>='0'){
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*f;
}
int pd(int lim){
	int res=1,t=0;
	for(int i=bg;i<=n;){
		t++;
		i=ne[i];
//		cout<<lim<<'r'<<i<<endl;
		if(i>=n) break;
		if(i==ne[i]){
			while(i<=n&&ne[i]==i) i++;
			if(i<=n){
				t=0;
				res++;
			}
		}else{
			if(t==lim){
				i++;
				while(i<=n&&!a[i]) i++;
				if(i<=n){
					res++;
					t=0;
				}
			}
		}
	}
//	cout<<res<<endl;
	return res<=k;
}
void work(){
	for(int i=1;i<=n;i++) a[i]=0,ne[i]=0;
	n=read();k=read();
	int h=0;
	for(int i=1;i<=n;i++){
		a[i]=read();
		if(a[i]) h++;
	}
	if(h<=k){
		puts("0");
		return;
	}
	while(!a[n]) n--;
	bg=1;
	while(!a[bg]) bg++;
	for(int i=bg;i<=n;i++){
		ne[i]=max(ne[i-1],a[i]+i);
	}
	int l=1,r=n+10;
	while(l<r){
		int mid=(l+r)>>1;
		if(pd(mid)){
			r=mid;
		}else{
			l=mid+1;
		}
	}
	if(l!=n+10)
	printf("%d\n",l);
	else
	puts("-1");
}
int main(){
//	freopen("ce.out","r",stdin);
	int t=read();
	while(t--){
		work();
	}
	return 0;
} 
全部评论

相关推荐

02-07 10:52
复旦大学 Java
混子不想混:非常能理解,感觉他们就靠着入行早,打压新人一样。我这个公司也是,天天干的累死累活,然后绩效打C,合着让新人被绩效,像是年底攒棺材本一样。总是打击之后,还会让人开始自我怀疑,是不是我努力的还不够,实际上并不是,就是他们不做人,故意打压新人。
点赞 评论 收藏
分享
喵_coding:年底缺人是短视频营造出来的 而且一般说的也很宽泛 不是特指后端
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务