某岛

… : "…アッカリ~ン . .. . " .. .
April 28, 2023

AtCoder Regular Contest 158

Problem C. All Pair Digit Sums

#159 的最后那个题 一样,我们也需要考虑容斥,计算进位所带来的代价。
注意枚举每一位的时候,进位可能会产生复杂的后效性(进位再进位…)我们不能仅仅考察那一位。。。
而是需要整个后缀都纳入考虑,比如对于一个末尾是 17 的数那么符合条件的就是末尾 >= 83 的数。。。
可以排序后二分查找或者线性做,复杂度 O(nlognlog(Ai))。

#include <lastweapon/io>
#include <lastweapon/number>
using namespace lastweapon;
const int N = int(2e5) + 9;
LL a[N], b[N];
int n;

int f(LL x) {
    int z = 0; while (x) {
        z += x % 10;
        x /= 10;
    }
    return z;
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif
    LL z = 0, c = 0;
    RD(n); REP(i, n) z += f(RD(a[i])); z <<= 1; z *= n;
    LL p10 = 1;
    REP(h, 15) {
        p10 *= 10; REP(i, n) b[i] = a[i] % p10; sort(b, b+n);
        REP(i, n) c += b+n-lower_bound(b, b+n, p10-b[i]);
    }
    cout << z - c*9 << endl;
}

Problem E. All Pair Shortest Paths

非常厉害的题,之前 fhc 出过三列的,这个题虽然只有两列,但是考察的东西更有趣了。

General 的 Floyd 是 O(n3) 的,格点图且没有负数的情况不存在向右又折返的情况,复杂性大为降低,但是状态依然是 O(n2) 的。
不过我们大量转移可以合并,我们只需要考察相邻的情况。

分类讨论后把 min 消掉,实际只有三种情况,且只和之前 dp 状态的差有关、
(这个十分 make sense,因为其实也只有上下,下上,和平推。交叉的情况肯定不存在。就像欧几里得平面里点的匹配一样囧)

于是我们可以开始根据这个差合并同类项!。。。然后惊喜的发现这个题最关键的性质。。。
对于平推的情况。。这些同类项的差依然是不变的!(寻找不变量!)
而对于另外两种情况,新的状态里它们又都被合并到一起了!。。。

于是我们就可以通过简单记录一个 offset 进行整体转移了。。后面就可以平推了。。甚至平衡树都不需要。。deque 即可。。
反而最后这步借助 offset 简化数据结构转移的题倒是非常常见的,甚至比线段树的懒标记还要简单(比如 COT6 里我们就用过)。