HDU7029 Median
传送
这场比赛直接罚坐5个点,这道题俩队友想的,我看别的题,结果不仅队友这题没过,我也啥都不会。
题解的切入点还是挺妙的,我们好像都没有往哪个方向上去想。
首先,\(m\)个中位数将序列分成了\(m+1\)段,那么任意两段的数都可以放到一个中位数的左右两侧,即“相消”。那么如果所有段互相消,全消没了必定是YES,但是否能全消没了呢?
想一想可以得出,如果最长的一段的长度小于其他段的长度之和,那么一定可以全消没,或者只留一个。方法就是不断拿剩下段最长的和最长段消,这样最长段消没后,剩下的段的长度要么最多相差1,要么有一些段没有动过。因此如果剩下的长度和是偶数的话就可以全消没,奇数的话就留1个。
而且留哪个和上述消的过程没有关系,那么不妨留最后一个。也就是说,当最大长度小于其他长度和时,必定是YES.
那如果大于呢?只要保证最大长度剩下的长度小于等于这个区间前面的中位数个数就可以了。这样每一个中位数在右边带一个最大长度区间的一个数,正好符合题目下取整的要求。
真的好像cf题,贴一个主要代码吧。
bool solve()
{
sort(b + 1, b + m + 1);
b[0] = 0, b[m + 1] = n + 1;
int sum = 0, Max = 0, num = 0;
for(int i = 1; i <= m + 1; ++i)
{
int len = b[i] - 1 - b[i - 1];
sum += len;
if(len > Max) Max = len, num = i - 1;
}
if(Max <= sum - Max) return 1;
else return Max - (sum - Max) <= num;
}