掌中之物,未必在掌握之中。|

2021hych

园龄:2年7个月粉丝:2关注:2

P4343 [SHOI2015]自动刷题机题解

题型考察

根据数据范围可以大致确定是 O(nlogn)O(n) 的算法才可以通过本题。考虑二分,可以发现问题具有单调性:设 check(x) 为长度为 x 时切的题数,则对于 x<y 而言,check(x)check(y)

思路

本题要求的是最大值和最小值分开讨论。
对于最小值:二分的对象为最小的 x 使得 check(x)=k,套用左边界模板。

while(l<r) {
	int mid=l+r>>1;
	if(check(mid)<=k) {
		ans1=mid;
		r=mid;
	}
	else l=mid+1;
}

对于最大值:二分的对象为最大的 x 使得 check(x)=k,套用右边界模板。

while(l<r) {
	int mid=l+r+1>>1;
	if(check(mid)>=k) {
		l=mid;
		ans2=mid;
	}
	else r=mid-1;
}

此刻二分答案结束。
考虑可能性问题,可以归纳出以下两种。
1.不存在 ans1 使得 check(ans1)=k
2.ans1>ans2
此刻特判结束。

代码实现

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=100010;
int n,k;
int a[N];
int l=1,r=1e16,ans1,ans2;
int check(int x) {
	int sum=0,num=0;
	for(int i=1;i<=n;i++) {
		sum=max(0ll,sum+a[i]);
		if(sum>=x) {
			sum=0;
			num++;
		}
	}
	return num;
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>n>>k;
	for(int i=1;i<=n;i++) cin>>a[i];
	while(l<r) {
		int mid=l+r>>1;
		if(check(mid)<=k) {
			ans1=mid;
			r=mid;
		}
		else l=mid+1;
	}
	if(ans1==0) {
		cout<<-1;
		return 0;
	}
	l=1,r=1e16;
	while(l<r) {
		int mid=l+r+1>>1;
		if(check(mid)>=k) {
			l=mid;
			ans2=mid;
		}
		else r=mid-1;
	}
	if(ans1>ans2) cout<<-1;
	else cout<<ans1<<" "<<ans2;
	return 0;
}

本文作者:2021hych

本文链接:https://www.cnblogs.com/2021hych/p/16503637.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   2021hych  阅读(43)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起