2025.2.11 CW 模拟赛

题面 & 题解

T1

算法

区间 dp.

思路

T1 sol.png

复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
int dfs(int l, int r, int x) { if (l > r) return 1; if (~f[l][r][x]) return f[l][r][x]; if (a[l] < x) return f[l][r][x] = dfs(l + 1, r, x); if (a[r] < x) return f[l][r][x] = dfs(l, r - 1, x); int mn = 1e9; for (int i = l; i <= r; ++i) if (a[i] >= x) mn = min(mn, a[i]); if (mn > x) return f[l][r][x] = dfs(l, r, mn); int ret = 0, flag = 0; for (int i = l; i <= r; ++i) { if (a[i] == x) flag = 1; if (flag and a[i] >= x) ret = (ret + 1ll * dfs(l, i, x + 1) * dfs(i + 1, r, x + 1)) % mod; } return f[l][r][x] = ret; }

T3

算法

构造.

思路

先考虑什么时候一定无解. 因为 \(a_i = i\) 的点是不动点, 所以该点两侧只能在内部交换, 那么如果左半部分中有需要被交换到右半部分中的的点 (右半部分同理), 则一定无解.

现在思考如何将 1 移动到 \(a_1\). 我们一定是需要不断向左挪的, 如果移不动 (例如 \(a_{x - 1} = x\)) 我们先交换一下顺序再移动即可. 对于 \(2 \sim n\), 同理即可.

复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
for (int i = 1; i <= n; ++i) { for (int j = 2; j < n; ++j) if (a[j] ^ j and a[j] == j + 1 and a[j - 1] ^ j - 1 and a[j - 1] ^ j) { ans.push_back({j - 1, j}); swap(pos[a[j]], pos[a[j - 1]]); swap(a[j], a[j - 1]); } for (int j = pos[i]; j > i; --j) { ans.push_back({j - 1, j}); swap(pos[a[j]], pos[a[j - 1]]); swap(a[j], a[j - 1]); } }

T4

算法

多源 bfs, 最小生成树.

思路

题目要求使得路径中最大权值最小, 很难不想到最小生成树. 同时有一个朴素的想法: 两两房子之间分别连边, 再在图中求最小生成树. 但是 \(m \le 2 \times 10^5\), \(\mathcal{O}(n^2)\) 连边会超时, 考虑优化.

经过思考可以发现, 又很多边其实是不优的, 所以我们通过多源 bfs, 从多个点出发进行染色, 只在颜色相撞的两点连边, 这样就可以保证边的数量不会太多, 从而保证复杂度正确.

在求完最小生成树之后, 两点的路径就唯一了, 这以后就可以通过倍增 lca / 树链剖分求出路径上的最大值即可.

代码链接.

posted @   Steven1013  阅读(3)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
展开