洛谷P5425 [USACO19OPEN]I Would Walk 500 Miles G

题目

https://www.luogu.com.cn/problem/P5425

思路

又是喜闻乐见的二分答案题,那么关键就是check函数的编写了。

我们考虑每次枚举一个\(mid\),然后判断是否存在一种分配方案使所有不同组奶牛之间的距离都\(\geq mid\)

对于这个距离\((2019201913x+2019201949y) \mod 2019201997\),根据同余性质,直接变成\(-84*x-48*y\),又:\(N\leq 7500\),所以距离很小,之后这个取模就没用了。

同时,根据式子,发现x和y越大,不满足条件的可能性就越大。

对于\(n\)号奶牛,我们看哪些可以和它分到不同组,哪些必须和它分到同一组。根据式子单调性可以发现,必须和它分到同一组的奶牛必然是\(n-1,n-2,...,n-t\)这样连续的一段。

同时,既然\(n-t-1\)号可以和\(n\)号分开,那它也必然可以和\(n-1,n-2,...n-t\)号分开,所以处理完\(n\)号就直接去处理\(n-t-1\)号,每头奶牛只访问一次,所以check函数是O(n)的。

总体时间复杂度为\(nlog2019201997\),可以承受。

代码

#include<cstdio>
#include<cstdlib>
#define mod 2019201997
#define ll long long
using namespace std;
int n,m;
ll f(int x,int y){
	return -84*x-48*y;
}
int check(ll x){
	int i=n,cnt=0,j=1;
	while(i>=1){
		j=i-1;
		while(j>=1&&f(j,i)<x){
			j--;
		}
		cnt++;
		i=j;
	}
	if(cnt>=m) return 1;
	else return 0;
}
int main(){
	int i,j;
	ll l=-mod,r=-1;
	scanf("%d%d",&n,&m);
	while(l<r){
		ll mid=(l+r)/2;
		if(check(mid)) l=mid;
		else r=mid-1;
	}
	printf("%lld",mod+l);
	// system("pause");
	return 0;
}
posted @ 2021-01-06 13:39  文艺平衡树  阅读(55)  评论(0编辑  收藏  举报