1 条题解

  • 0
    @ 2025-10-25 22:28:06

    题目分析

    这是 POI 2012 Leveling Ground 的题解代码。题目要求:

    • 给定长度为 nn 的数组 hh
    • 每次操作可以将一个区间增加/减少 aa,或者增加/减少 bb
    • 目标是将整个数组变为 00
    • 求最小操作次数

    核心思路

    1. 差分转化

    代码的关键是将原问题转化为差分数组上的问题:

    for (int i = n + 1; i >= 1; i--) {
        h[i] = h[i] - h[i - 1];
        // ...
    }
    

    这样区间操作就变成了对两个端点的操作。

    2. 数论基础

    c=gcd(a,b)c = \gcd(a, b),只有当所有 h[i]h[i] 都能被 cc 整除时才有解:

    if (h[i] % c != 0) {
        print(-1);
        return 0;
    }
    

    3. 扩展欧几里得

    对于每个差分值 h[i]h[i],求解方程:

    ax+by=h[i]a \cdot x + b \cdot y = h[i]

    使用扩展欧几里得算法:

    exgcd(a, b, x[i], y[i]);
    x[i] *= h[i] / c;
    y[i] *= h[i] / c;
    

    4. 寻找最优解

    由于方程有多组解,代码通过调整找到使 x+y|x| + |y| 最小的解:

    // 四种调整方式,寻找最优的(x,y)对
    p = (x[i] % A + A) % A;
    q = (h[i] - p * a) / b;
    // ...
    

    5. 贪心调整

    最后使用优先队列进行贪心调整,使得总的 xx 和为 00

    while (sumx != 0) {
        ans -= q.top().first;
        // 调整x[i]和y[i]的值
        // ...
    }
    

    复杂度分析

    • 扩展欧几里得:O(logmin(a,b))O(\log \min(a,b)) 每个元素
    • 贪心调整:O(nlogn)O(n \log n)
    • 总复杂度:O(nlogn)O(n \log n)

    关键点

    1. 差分转化:将区间操作转化为单点操作
    2. 通解调整:利用扩展欧几里得的通解形式找到最优解
    3. 贪心平衡:通过优先队列平衡总的 xx

    这个解法巧妙地将区间操作问题转化为数论和贪心问题,是竞赛中典型的数学+算法结合题型。

    • 1

    信息

    ID
    4125
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者