黑龙江农垦科技职业学院喜迎寒假多校联赛2(快乐ak场)(D题详解)

黑龙江农垦科技职业学院喜迎寒假多校联赛2(快乐ak场)D题详解

从比赛到现在,终于算是想通了,记录一下。

AC代码

#include<iostream>

using namespace std;

typedef unsigned long long ull;

const int N = 1e6 + 10;

int n,m;
ull a[N],l,r;

bool check(ull mid)
{
   ull sum = 0;
   ull cnt = 1;
   for(int i = 0;i < n;i ++)
   {
   	sum += a[i];
   	if(sum > mid)
   	{
   		sum = a[i];
   		cnt ++;
   	}
   }
   if(cnt <= m)return true;
   return false;
}

int main()
{
   scanf("%d %d",&n,&m);
   for(int i = 0;i < n;i ++)
   {
   	scanf("%llu",&a[i]);
   	r += a[i];
   }
   //cout << check(6) << endl; 
   while(l < r)
   {
   	ull mid = (l + r) >> 1;
   	//mid >= m
   	if(check(mid))r = mid;
   	else l = mid + 1;
       //cout << "l = " << l << " r = " << r << endl; 
   }
   printf("%llu",l);
}

值得一提的是,这样写,就已经足够AC这个题,但是还有一处逻辑错误,二分的左边界应该是 m a x ( a [ i ] ) max(a[i]) max(a[i]),而不是0.

分析:

黑龙江农垦科技职业学院喜迎寒假多校联赛2(快乐ak场)(D题详解)

真正的划分过程如上,我们规定 m i d mid mid 这个数是能达到的最大值的最小值。这意味着 : 当 s u n < = m i d sun <= mid sun<=mid 的时候,都可以划分成一个队伍。如果 >sum,就记录得到的队伍数量 +1,这样的划分,使得 m i d mid mid向着 a n s ans ans不断靠近。
图中,从左往右,能组成 c n t cnt cnt支队伍的数量是在逐渐减少的。
如果拿个人max,来作为划分边界,毫无疑问的,能划分到n个队伍。 m i d mid mid从左往右能划分的队伍的数量越来越少,在ans处,恰好能划分成m,这也就是我们的答案,如果 > ans,肯定能划分成m支队伍,所以:

if(check(true)) r = mid;

是从这里转换的。

下面是个人错误的点

之所以迷了这么久,是因为划分的条件搞错了。黑龙江农垦科技职业学院喜迎寒假多校联赛2(快乐ak场)(D题详解)
之前我是这么划分的,导致更新区间一直是错误的状态。
能分成 m 队,这个是很容易做到的事情,因为在 mid = 个人最大 的时候,这个条件已经达成了。总实力的不断提高,能划分成的队伍肯定是越来越少的, > ans 组成一队,实际上 mid 的值是没有具体意义的,最后二分出来的值,肯定不是答案。

上一篇:快乐AK场2 D issue与lifehappy给学生分组 二分


下一篇:Codeforces 76D - Plus and xor - [加、且和异或]