1 条题解

  • 0
    @ 2025-12-3 15:58:46

    题意理解
    有 ( n ) 个区域,初始时第 ( i ) 个区域有 ( a_i ) 个等位学生和 ( b_i ) 个空位。
    每个时刻发生两件事:

    1. 每个区域的学生尽可能坐下(即 ( \min(x_i, y_i) ) 个学生坐下)。
    2. 每个区域的剩余学生移动到下一个区域(环形移动)。

    有 ( 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 ) 的区间内,累积过剩量不超过某个阈值。

    算法流程

    1. 计算过剩量
      ( c_i = a_i - b_i )。
      计算长度为 ( 2n ) 的前缀和数组 ( A[i] = \sum_{j=1}^i c_j )(下标从 1 开始,环形复制)。

    2. 寻找最小前缀和位置
      在 ( A[n..2n] ) 中找到最小值所在位置 ( pos ),以此作为起点(贪心选择最有利的起点,使得后续检查更容易满足条件)。

    3. 二分答案
      二分最少时刻 ( t )。
      对每个 ( t ),检查是否存在一种离开 ( k ) 人的方案,使得所有区域在 ( t ) 时刻后无学生等待。

    4. 检查函数 check(t)

      • 维护一个单调队列,存储候选位置(其 ( A ) 值递增)。
      • 从 ( pos ) 向左扫描到 ( pos-n )(即逆时针一圈)。
      • 对每个位置 ( i ),计算其前方 ( t ) 个位置内的最大过剩量累积值,并与 ( k ) 比较。
      • 核心判断:若需要移除的学生数超过 ( k ),则 ( t ) 不可行。
    5. 特殊情况

      • 若 ( 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
    上传者