1 条题解
-
0
题意理解
有 ( n ) 个区域,初始时第 ( i ) 个区域有 ( a_i ) 个等位学生和 ( b_i ) 个空位。
每个时刻发生两件事:- 每个区域的学生尽可能坐下(即 ( \min(x_i, y_i) ) 个学生坐下)。
- 每个区域的剩余学生移动到下一个区域(环形移动)。
有 ( k ) 名学生会在时刻 0 离开,但不知道他们具体在哪些区域。
问在所有可能的 ( k ) 人离开分布中,最少经过多少时刻才能让所有区域都没有等位学生。问题转化
设 ( c_i = a_i - b_i ),表示区域 ( i ) 的“学生过剩量”(若为正,表示学生多于空位;若为负,表示空位多于学生)。
经过 ( t ) 个时刻后,每个区域的学生过剩量会累积转移,最终目标是所有区域的学生过剩量 ≤ 0(即所有学生都能坐下)。
因为学生可以在坐下后离开,所以问题转化为:
选择 ( k ) 名学生离开,使得经过 ( t ) 个时刻后,所有区域的累积过剩量 ≤ 0。
最小化 ( t )。关键观察
设 ( S_i = \sum_{j=1}^i c_j )(前缀和),环形考虑,将序列复制一遍。
可以发现,对于给定的 ( t ),我们需要检查是否存在一种离开 ( k ) 人的方案,使得在任意长度为 ( t+1 ) 的区间内,累积过剩量不超过某个阈值。算法流程
-
计算过剩量
( c_i = a_i - b_i )。
计算长度为 ( 2n ) 的前缀和数组 ( A[i] = \sum_{j=1}^i c_j )(下标从 1 开始,环形复制)。 -
寻找最小前缀和位置
在 ( A[n..2n] ) 中找到最小值所在位置 ( pos ),以此作为起点(贪心选择最有利的起点,使得后续检查更容易满足条件)。 -
二分答案
二分最少时刻 ( t )。
对每个 ( t ),检查是否存在一种离开 ( k ) 人的方案,使得所有区域在 ( t ) 时刻后无学生等待。 -
检查函数 check(t)
- 维护一个单调队列,存储候选位置(其 ( A ) 值递增)。
- 从 ( pos ) 向左扫描到 ( pos-n )(即逆时针一圈)。
- 对每个位置 ( i ),计算其前方 ( t ) 个位置内的最大过剩量累积值,并与 ( k ) 比较。
- 核心判断:若需要移除的学生数超过 ( k ),则 ( t ) 不可行。
-
特殊情况
- 若 ( k = \sum a_i )(所有人离开),则答案为 0。
- 由于题目保证 ( \sum a_i \leq \sum b_i ),所以最终一定有解。
复杂度分析
- 前缀和计算:( O(n) )。
- 二分答案:( O(\log n) ) 次检查。
- 每次检查:单调队列扫描 ( O(n) )。
- 总复杂度:( O(n \log n) ),满足 ( \sum n \leq 5 \times 10^5 )。
算法标签
- 前缀和与差分
- 单调队列优化
- 二分答案
- 环形数组处理
样例验证
样例 1:
( n=3, k=0, a=[1,1,4], b=[5,1,4] )
( c=[-4,0,0] ),经过 1 个时刻即可满足,输出 1。样例 2:
( n=4, k=0, a=[1,2,3,4], b=[4,3,2,1] )
( c=[-3,-1,1,3] ),需要 4 个时刻,输出 4。样例 3:
( k = \sum a_i = 6 ),所有人离开,输出 0。样例 4:
( k=1 ),最优情况下需要 2 个时刻,输出 2。总结
将学生移动和坐下过程转化为过剩量的累积与转移问题。
通过前缀和、单调队列和二分答案,高效求解最小时刻。
关键在于将“离开 k 人”的灵活性转化为对累积过剩量的约束检查。
- 1
信息
- ID
- 5766
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者