COMPFEST 15 - Preliminary Online Mirror 补题

A Ambitious Kid

链接

题面翻译

给定一个 $N(1 \leq N \leq 10^5)$,给定一个数组 $A_i$,每次可以让一个数 $ +1/-1 $,求至少多少次操作能使 $A_1 \times A_2 \times A_3 \times \cdots \times A_N=0$。

Sol

签到题。

答案是所有数绝对值最小的那个。

B Completely Searching for Inversions

链接

题面翻译

给定一个有 $ N $ 个结点的有向无环图。结点 $ i $ 的出度为 $ S_i $。结点 $ i $ 的第 $ j $ 条出边指向 $ L_{i, j} $,边权为 $ W_{i, j} \text{ } (0 \le W_{i, j} \le 1) $。给出的图保证从结点 $ 1 $ 出发可以到达所有结点。

给定初始为空的数组 $ Z $。

定义函数 $ \texttt{dfs} $ 如下:

// 以结点 i 为起点进行 dfs
void dfs(int i) {
    // 遍历 i 的每条出边
    for(int j = 1; j <= S[i]; j++) {
        Z.push_back(W[i][j]); // 将当前边的边权加入数组 Z 的末尾
        dfs(L[i][j]); // 从下一个结点继续 dfs
    }
}

请注意,以上函数并没有记录经过的结点,所以有些结点可能被经过不止一次。

在主函数中,程序调用了一次 $ \texttt{dfs(1)} $,得到了一个只包含 $ 0 $ 和 $ 1 $ 的数组 $ Z $。请你求出数组 $ Z $ 的逆序对数。

由于答案可能很大,你只需要输出答案对 $ 998 \text{ } 244 \text{ } 353 $ 取模的值。

Sol

考虑暴力时重复的子问题:dfs 过程中一个点会被经过多次,于是考虑优化掉这部分。

发现从一个节点往下 dfs,对 $ Z $ 序列的新增区间相同,新产生的贡献 = 新增区间逆序对个数 + 原 $ Z $ 序列 $ 1 $ 的个数 $ \times $ 新增区间 $ 0 $ 的个数。

于是对于 $ DAG $ 上的每一个点,用 $ O(n) \ dfs $ 维护出 从该点遍历对 $ Z $ 序列新增区间中 $ 0 $ 的个数/$ 1 $ 的个数/逆序对个数,然后按儿子合并即可。

posted @ 2023-09-06 21:53  象征阳光  阅读(11)  评论(0)    收藏  举报  来源