COMPFEST 15 - Preliminary Online Mirror 补题

A Ambitious Kid

链接

题面翻译

给定一个 N(1N105),给定一个数组 Ai,每次可以让一个数 +1/1,求至少多少次操作能使 A1×A2×A3××AN=0

Sol

签到题。

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

B Completely Searching for Inversions

链接

题面翻译

给定一个有 N 个结点的有向无环图。结点 i 的出度为 Si。结点 i 的第 j 条出边指向 Li,j,边权为 Wi,j (0Wi,j1)。给出的图保证从结点 1 出发可以到达所有结点。

给定初始为空的数组 Z

定义函数 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
    }
}

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

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

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

Sol

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

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

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

posted @   象征阳光  阅读(7)  评论(0编辑  收藏  举报  
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示