CF949D Curfew solution

题目链接

今天给大家整点二分加贪心的题

题意

这个题是说在一个走廊上有n个房间,2个宿管从两端向中间查询,当宿管发现房间里的人数不足b个时,就记录下并锁门,两个宿管各自记录一边的,特别的,当n为奇数时,左边的宿管多查一个房间,求两个宿管记录数最大值的最小值。(P&S:当人数多于b个时,学生可以藏在床底下以躲过宿管的查房)

思路

像这种题,一看就是个二分题,那么我们该怎么验证可行性呢?
很容易想到如果一个房间不能满足,那么我们的最优策略就是留下一个空房间,将人往中间集中
所以可以得到中间一定满足的是一段连续的序列,故我们可以二分这个序列的最左端(也可以说是最右端),然后得到一个最大值。
如图:
在这里插入图片描述

代码

具体操作见代码

bool check(int x)
{
	ll dis = 1ll * d * (x + 1);
	int p1 = 1, p2 = n, s1 = x + 1, s2 = n - x;
	for (int i = 1; i <= n; i++)
		a[i] = t[i];
	while (s1 < s2)
	{
		int tmp = b;
		while (a[p1] < tmp) tmp -= a[p1++];
		a[p1] -= tmp;
		if (p1 - s1 > dis)
			return 0;
		if (n % 2 == 1 && s1 == (n + 1) / 2)
			break;
		tmp = b;
		while (a[p2] < tmp)	
			tmp -= a[p2--];
		a[p2] -= tmp;
		if (s2 - p2 > dis)
			return 0;
		dis += d, s1++, s2--;
	}
	return 1;
}
int main()
{
    rd(n), rd(d), rd(b);
	for (int i = 1; i <= n; i++)
		rd(t[i]);
	int l = 0, r = (n + 1) / 2, ans;
	while (l <= r)
	{
		int mid = (l + r) >> 1;
		if (check(mid))
			r = mid - 1, ans = mid;
		else
			l = mid + 1;
	}
	pt(ans);
    return 0;
}

谢谢

猜你喜欢

转载自blog.csdn.net/qq_43537070/article/details/107562089