D46 2-SAT+线段树优化+二分 [ARC069F] Flags
视频链接:D46 2-SAT+线段树优化+二分 [ARC069F] Flags_哔哩哔哩_bilibili
[ARC069F] Flags - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
// 2-SAT+线段树优化+二分 O(nlognlogx) #include <iostream> #include <cstring> #include <algorithm> using namespace std; #define mid ((l+r)>>1) #define ls (u<<1) #define rs (u<<1|1) const int N=20010,M=N*10; int head[M],ne[N*40],to[N*40],idx; void add(int x,int y){ to[++idx]=y;ne[idx]=head[x];head[x]=idx; } int dfn[M],low[M],stk[M],scc[M],tim,top,sc; int n,tot,id[M]; struct F{ int x,id; //坐标,编号 F(int x=0):x(x){} bool operator<(const F& b)const{return x<b.x;} }f[N]; //旗子 void build(int u,int l,int r){ id[u]=++tot; //节点编号 if(l==r){ int x=f[l].id; add(id[u],x<=n?x+n:x-n); //叶子向反点连边 return; } build(ls,l,mid); build(rs,mid+1,r); add(id[u],id[ls]); add(id[u],id[rs]); //父向子连边 } void link(int u,int l,int r,int x,int y,int p){ if(x>r||y<l) return; if(x<=l&&r<=y){ add(p,id[u]); //p点向区间id[u]连边 return; } link(ls,l,mid,x,y,p), link(rs,mid+1,r,x,y,p); } #undef mid void tarjan(int x){ dfn[x]=low[x]=++tim; stk[++top]=x; for(int i=head[x];i;i=ne[i]){ int y=to[i]; if(!dfn[y]){ //若y尚未访问 tarjan(y); low[x]=min(low[x],low[y]); } else if(!scc[y]) //若y已访问且未处理 low[x]=min(low[x],dfn[y]); } if(low[x]==dfn[x]){ //若x是SCC的根 ++sc; for(int y=-1;y!=x;) scc[y=stk[top--]]=sc; } } bool check(int mid){ memset(head,0,sizeof(head)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(scc,0,sizeof(scc)); idx=tim=top=sc=0; build(1,1,tot=2*n); for(int i=1,x,y;i<=2*n;i++){ x=upper_bound(f+1,f+1+2*n,F(f[i].x-mid))-f; y=lower_bound(f+1,f+1+2*n,F(f[i].x+mid))-f-1; link(1,1,2*n,x,i-1,f[i].id); //x是距离<mid的左下标 link(1,1,2*n,i+1,y,f[i].id); //y是距离<mid的右下标 } for(int i=1;i<=2*n;i++) if(!dfn[i]) tarjan(i); for(int i=1;i<=n;i++) if(scc[i]==scc[i+n]) return 0; return 1; } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d%d",&f[i].x,&f[i+n].x); f[i].id=i,f[i+n].id=i+n; //点的编号 } sort(f+1,f+n*2+1); //按x排序 int l=0,r=f[2*n].x-f[1].x+1,mid; while(l+1<r){ //二分距离 mid=(l+r)/2; check(mid)?l=mid:r=mid; } printf("%d",l); }
UVA1146 Now or later - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
// 2-SAT+线段树优化+二分 O(nlognlogx) #include <iostream> #include <cstring> #include <algorithm> #include <vector> using namespace std; #define mid ((l+r)>>1) #define ls (u<<1) #define rs (u<<1|1) const int N=4010,M=N<<2; vector<int> v[M]; //邻接表 int dfn[M],low[M],stk[M],scc[M],tim,top,sc; int n,tot,id[M]; struct F{ int x,id; //坐标,编号 F(int x=0):x(x){} bool operator<(const F& b)const{return x<b.x;} }f[N]; //旗子 void build(int u,int l,int r){ id[u]=++tot; //节点编号 if(l==r){ int x=f[l].id; v[id[u]].push_back(x<=n?x+n:x-n); //叶子向反点连边 return; } build(ls,l,mid); build(rs,mid+1,r); v[id[u]].push_back(id[ls]); v[id[u]].push_back(id[rs]); //父向子连边 } void link(int u,int l,int r,int x,int y,int p){ if(x>r||y<l) return; if(x<=l&&r<=y){ v[p].push_back(id[u]); //p点向区间id[u]连边 return; } link(ls,l,mid,x,y,p), link(rs,mid+1,r,x,y,p); } #undef mid void tarjan(int x){ dfn[x]=low[x]=++tim; stk[++top]=x; for(int y:v[x]){ if(!dfn[y]){ //若y尚未访问 tarjan(y); low[x]=min(low[x],low[y]); } else if(!scc[y]) //若y已访问且未处理 low[x]=min(low[x],dfn[y]); } if(low[x]==dfn[x]){ //若x是SCC的根 ++sc; for(int y=-1;y!=x;) scc[y=stk[top--]]=sc; } } bool check(int mid){ for(int i=1;i<=8*n;++i) v[i].clear(); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(scc,0,sizeof(scc)); memset(stk,0,sizeof(stk)); tim=top=sc=0; build(1,1,tot=2*n); for(int i=1,x,y;i<=2*n;i++){ x=upper_bound(f+1,f+1+2*n,F(f[i].x-mid))-f; y=lower_bound(f+1,f+1+2*n,F(f[i].x+mid))-f-1; link(1,1,2*n,x,i-1,f[i].id); //x是距离<mid的左下标 link(1,1,2*n,i+1,y,f[i].id); //y是距离<mid的右下标 } for(int i=1;i<=2*n;i++) if(!dfn[i]) tarjan(i); for(int i=1;i<=n;i++) if(scc[i]==scc[i+n]) return 0; return 1; } int main(){ while(scanf("%d",&n)!=EOF){ for(int i=1;i<=n;i++){ scanf("%d%d",&f[i].x,&f[i+n].x); f[i].id=i,f[i+n].id=i+n; //点的编号 } sort(f+1,f+n*2+1); //按x排序 int l=0,r=1e7+1,mid; while(l+1<r){ //二分距离 mid=(l+r)>>1; check(mid)?l=mid:r=mid; } printf("%d\n",l); } }
分类:
D 图论
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
2023-08-18 C27 线段树 区间最大公约数
2023-08-18 C26 线段树 区间最大子段和