Codeforces 1710D Recover the Tree - 构造
题目传送门
因为一些奇奇怪怪的原因被迫去打 acm,sad....
不难注意到一条很简单的性质:如果两个连通区间交非空,那么它们的交和并都是连通的。
考虑把 当做根,根据这条性质可以知道剩下极大的连通区间两两无交且并集为 。
注意到每个极大连续区间可以当做一个子问题,先假设我们递归得到了满足题目条件的这样一些连通块。
现在考虑把它们连接起来,使得满足根的限制,以及它们之间的限制(不存在连通区间)。
对于一个极大连通区间
如果存在一个连通区间 满足 ,设 是满足这个条件最小的 ,那么仅需把 接到 上即可满足所有连通块之间的限制。根据最开始那条性质,也容易知道满足根给它的限制。
如果不存在的话,如果 不是连通区间,那么直接把这个连通块接在 上就可以了,否则把它接在 上,这个 是最小的满足 且 为连通区间的 。
注意到最后这一种情况可能对满足连通块之间的限制不是那么地显然。但是注意到一个性质,就是 之间一定还包含一个极大连续区间,否则话不可能有满足条件的树。
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | #include <bits/stdc++.h> using namespace std; const int N = 2e3 + 5; int T; int n; char buf[N]; bool f[N][N]; void dividing( int l, int r) { bool flg = true ; for ( int l0 = l + 1, r0 = r; l0 <= r; l0 = r0 + 1, r0 = r) { while (!f[l0][r0]) r0--; dividing(l0, r0); for ( int i = l0; i <= r; i++) { if (f[l][i]) { if (i > r0) { if (flg) { printf ( "%d %d\n" , r0, i); flg = false ; } else { printf ( "%d %d\n" , l, l0); } } else { flg = true ; printf ( "%d %d\n" , l, i); } break ; } } } } void solve() { scanf ( "%d" , &n); for ( int i = 1; i <= n; i++) { scanf ( "%s" , buf + i); for ( int j = i; j <= n; j++) { f[i][j] = (buf[j] == '1' ); } } dividing(1, n); } int main() { scanf ( "%d" , &T); while (T--) { solve(); } return 0; } |
分类:
杂-构造
标签:
Codeforces
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
2017-07-27 bzoj 3309 DZY Loves Math - 莫比乌斯反演 - 线性筛