CF1710D Recover the Tree
CF1710D Recover the Tree
题意
根据题意构造出一棵合法的树。
有 个点。 表示编号在 的点是否连通。
。
保证有解。
思路
显然是先考虑小区间,然后合并到大区间。
思考只有 的情况怎么做。
不能连边。 可以连边。但是不可以有更小的区间连通。
一种构造方案是连 。
当 时无解。
考虑一般情况。
考虑按顺序一个一个加点。现在加到点 。
由于树的连通块形式,如果 连通。且 ,那么 也是连通的。即交和并都是连通的。
那么此时 已经有了若干个极大的连通区间。
假设 ,如何合并连通块。
参考之前的构造,首先连 ,如果中间还有多个连通块,然后连 和第二块连通块的头,然后连 和其他连通块的尾。
小到大枚举 ,从大到小枚举 容易证明是对的。怎么想到的我就不知道了。
时间复杂度 。
code
好写的。
#include<bits/stdc++.h> #define sf scanf #define pf printf #define rep(x,y,z) for(int x=y;x<=z;x++) #define per(x,y,z) for(int x=y;x>=z;x--) using namespace std; typedef long long ll; namespace wing_heart { constexpr int N=2e3+7; #define gc getchar typedef pair<int,int> pii; #define fi first #define se second int t; int n; char a; vector<int> vec[N]; bool cmp (int a,int b) { return a>b; } void main() { sf("%d",&t); while(t--) { sf("%d",&n); rep(i,1,n) vec[i].clear(); rep(i,1,n) rep(j,i,n) { a=gc(); while(a!='1' && a!='0') a=gc(); if(a=='1' && j!=i) vec[j].push_back(i); } rep(i,1,n) sort(vec[i].begin(),vec[i].end(),cmp); stack<pii> que; rep(r,1,n) { que.push({r,r}); for(int x : vec[r]) { vector<pii> tmp; if(que.top().fi<=x) continue; while(que.size() && que.top().se>=x) tmp.push_back(que.top()), que.pop(); pf("%d %d\n",x,r); if(tmp.size()>2) pf("%d %d\n",r,tmp[tmp.size()-2].fi); rep(i,1,(int)tmp.size()-3) pf("%d %d\n",x,tmp[i].se); que.push({tmp.back().fi,r}); } } } } } int main() { #ifdef LOCAL freopen("in.txt","r",stdin); freopen("my.out","w",stdout); #endif wing_heart :: main(); }
本文来自博客园,作者:wing_heart,转载请注明原文链接:https://www.cnblogs.com/wingheart/p/18719695
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下