【ARC069F】Flags 2-sat+线段树优化建图+二分
Description
数轴上有 n 个旗子,第 ii 个可以插在坐标 xi或者 yi,最大化两两旗子之间的最小距离。
Input
第一行一个整数 N。
接下来 N 行每行两个整数 xi,yi
Output
一个整数表示答案。
Sample Input
Sample #1
3
1 3
2 5
1 9
Sample #2
5
2 2
2 2
2 2
2 2
2 2
Sample #3
22
93 6440
78 6647
862 11
8306 9689
798 99
801 521
188 206
6079 971
4559 209
50 94
92 6270
5403 560
803 83
1855 99
42 504
75 484
629 11
92 122
3359 37
28 16
648 14
11 269
Sample Output
Sample #1
4
Sample #2
0
Sample #3
17
HINT
2≤N≤10^4
1≤xi,yi≤10^9
Sol
线段树优化建图+2-sat+二分。
首先我们二分答案k,然后把一个点向离他距离为k以内的点的反点连边(2-sat的边表示依赖关系),之后直接判断有没有解,但是显然这样会TLE,因为边的个数是\(n^2\)级别的。
所以考虑线段树优化建图,步骤为:
1.按照2n个点排序,建出线段树,每个点向他的父亲连边,最底层点向这个点代表的点的反点连边(因为2-sat连的是反点,别的题没有必要)
2.对于每个点进行编号(一共2n个)。
3.我们考虑每个点,找到和他距离k以内的点的两段区间,然后用这个点按照线段树区间查找的方式向logn个区间连边。(注意一定要跳过自己对应的点,因为这代表着自己的反点,不能连边)
中间有点细节,要注意一下。
之后就是2-sat的经典应用了。
Code
#include <bits/stdc++.h>
using namespace std;
struct seg{int l,r,id;seg(int l=0,int r=0,int id=0):l(l),r(r),id(id){}}s[500005];
int n,P,Index,L,p[100005][2],dfn[100005],low[100005],in[100005],cnt,bel[100005],b[100005],x[100005],y[100005],X[100005],Y[100005],vis[100005];
pair<int,int>pos[100005];vector<int>e[100005];stack<int>q;
void build(int x,int L,int R)
{
s[x]=seg(L,R,++P);
if(x>>1) e[s[x>>1].id].push_back(s[x].id);
if(L==R){e[s[x].id].push_back(p[pos[L].first][pos[L].second^1]);return;}
int mid=(L+R)>>1;build(x*2,L,mid);build(x*2+1,mid+1,R);
}
void ins(int x,int L,int R,int u)
{
if(L>R) return;
if(s[x].l==L&&s[x].r==R){e[u].push_back(s[x].id);return;}
int mid=(s[x].l+s[x].r)>>1;
if(R<=mid) ins(x*2,L,R,u);else if(L>mid) ins(x*2+1,L,R,u);
else ins(x*2,L,mid,u),ins(x*2+1,mid+1,R,u);
}
void tarjan(int x)
{
dfn[x]=low[x]=++Index;in[x]=1;q.push(x);
for(int i=0;i<e[x].size();i++)
if(!dfn[e[x][i]]) tarjan(e[x][i]),low[x]=min(low[x],low[e[x][i]]);
else if(in[e[x][i]]) low[x]=min(low[x],dfn[e[x][i]]);
if(dfn[x]==low[x]) for(cnt++;;){int now=q.top();q.pop();in[now]=0;bel[now]=cnt;if(now==x) break;}
}
bool chk(int k)
{
P=cnt=Index=0;for(int i=0;i<=n*5;i++) e[i].clear();while(!q.empty()) q.pop();
memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low));memset(in,0,sizeof(in));memset(bel,0,sizeof(bel));
for(int i=1;i<=n;i++) p[i][0]=++P,p[i][1]=++P;
build(1,1,L);
for(int i=1;i<=n;i++)
ins(1,upper_bound(b+1,b+L+1,X[i]-k)-b,x[i]-1,p[i][0]),ins(1,x[i]+1,lower_bound(b+1,b+L+1,X[i]+k)-b-1,p[i][0]),
ins(1,upper_bound(b+1,b+L+1,Y[i]-k)-b,y[i]-1,p[i][1]),ins(1,y[i]+1,lower_bound(b+1,b+L+1,Y[i]+k)-b-1,p[i][1]);
for(int i=1;i<=P;i++) if(!dfn[i]) tarjan(i);int ok=1;
for(int i=1;i<=n;i++) if(bel[p[i][0]]==bel[p[i][1]]) ok=0;
return ok;
}
int find(int I,int P,int x)
{
int res,l=1,r=L;
for(int mid=(l+r)>>1;l<=r;mid=(l+r)>>1)
{
if(b[mid]==x&&!vis[mid]) res=mid,r=mid-1;
else if(b[mid]>x) r=mid-1;else l=mid+1;
}
vis[res]=1;pos[res]=make_pair(I,P);return res;
}
int main()
{
scanf("%d",&n);int l=0,r=1e9,ans;
for(int i=1;i<=n;i++) scanf("%d%d",&X[i],&Y[i]),b[++L]=X[i],b[++L]=Y[i];
sort(b+1,b+L+1);
for(int i=1;i<=n;i++) x[i]=find(i,0,X[i]),y[i]=find(i,1,Y[i]);
for(int mid=(l+r)>>1;l<=r;mid=(l+r)>>1) if(chk(mid)) l=mid+1,ans=mid;else r=mid-1;
printf("%d\n",ans);
}
【ARC069F】Flags 2-sat+线段树优化建图+二分的更多相关文章
- 2-sat 问题 【例题 Flags(2-sat+线段树优化建图)】
序: 模拟赛考了一道 2-sat 问题.之前从来没听过…… 考完才发现其实这个东东只要一个小小的 tarjan 求强连通分量就搞定了. 这个方法真是巧妙啊,拿来讲讲. What is it? [・_・ ...
- BZOJ5017 [SNOI2017]炸弹 - 线段树优化建图+Tarjan
Solution 一个点向一个区间内的所有点连边, 可以用线段树优化建图来优化 : 前置技能传送门 然后就得到一个有向图, 一个联通块内的炸弹可以互相引爆, 所以进行缩点变成$DAG$ 然后拓扑排序. ...
- 【BZOJ3681】Arietta 树链剖分+可持久化线段树优化建图+网络流
[BZOJ3681]Arietta Description Arietta 的命运与她的妹妹不同,在她的妹妹已经走进学院的时候,她仍然留在山村中.但是她从未停止过和恋人 Velding 的书信往来.一 ...
- 【bzoj5017】[Snoi2017]炸弹 线段树优化建图+Tarjan+拓扑排序
题目描述 在一条直线上有 N 个炸弹,每个炸弹的坐标是 Xi,爆炸半径是 Ri,当一个炸弹爆炸时,如果另一个炸弹所在位置 Xj 满足: Xi−Ri≤Xj≤Xi+Ri,那么,该炸弹也会被引爆. 现在 ...
- 【bzoj4699】树上的最短路(树剖+线段树优化建图)
题意 给你一棵 $n$ 个点 $n-1$ 条边的树,每条边有一个通过时间.此外有 $m$ 个传送条件 $(x_1,y_1,x_2,y_2,c)$,表示从 $x_1$ 到 $x_2$ 的简单路径上的点可 ...
- 【BZOJ4276】[ONTAK2015]Bajtman i Okrągły Robin 线段树优化建图+费用流
[BZOJ4276][ONTAK2015]Bajtman i Okrągły Robin Description 有n个强盗,其中第i个强盗会在[a[i],a[i]+1],[a[i]+1,a[i]+2 ...
- 【bzoj3073】[Pa2011]Journeys 线段树优化建图+堆优化Dijkstra
题目描述 Seter建造了一个很大的星球,他准备建造N个国家和无数双向道路.N个国家很快建造好了,用1..N编号,但是他发现道路实在太多了,他要一条条建简直是不可能的!于是他以如下方式建造道路:(a, ...
- 【bzoj4383】[POI2015]Pustynia 线段树优化建图+差分约束系统+拓扑排序
题目描述 给定一个长度为n的正整数序列a,每个数都在1到10^9范围内,告诉你其中s个数,并给出m条信息,每条信息包含三个数l,r,k以及接下来k个正整数,表示a[l],a[l+1],...,a[r- ...
- BZOJ_4276_[ONTAK2015]Bajtman i Okrągły Robin_线段树优化建图+最大费用最大流
BZOJ_4276_[ONTAK2015]Bajtman i Okrągły Robin_线段树优化建图+最大费用最大流 Description 有n个强盗,其中第i个强盗会在[a[i],a[i]+1 ...
随机推荐
- js操作window
js操作window 常用属性 window.closed // window是否关闭 window.length // iframe个数 window.name // 获取和设置window的名字 ...
- Vertrigo Serv + testlink 环境搭建
今天偶要教大家,使用VertrigoServ来搭建PHP服务器平台.有兴趣的你将会马上拥有一台PHP的WEB服务器哦,呵呵! 第一次给偶的感觉类似于我们租用的PHP虚拟主机.功能可和APPSERV媲美 ...
- How To Install Git on CentOS 7
Introduction Version control has become an indispensable tool in modern software development. Versio ...
- Halcon学习之一:查询图像参数
版权声明:本文为博主原创文章,未经博主允许不得转载. 1.get_grayval ( Image : : Row, Column : Grayval ) 计算Image图像中坐标为(Row,Colum ...
- POJ1657
1.题目链接地址 http://poj.org/problem?id=1657 2.源代码 #include<iostream> using namespace std; int main ...
- Spark,一种快速数据分析替代方案
原文出处:http://www.ibm.com/developerworks/library/os-spark/ Spark 是一种与 Hadoop 相似的开源集群计算环境,但是两者之间还存在一些不同 ...
- 用Golang为Python编写模块
Go里面需要显示的引入C模块, 让编译器支持生成动态链接库, 并且在代码中可以使用C语言的数据类型,这个至关重要. Calling Go code from Python code 摘取一个最简单例子 ...
- js的两种查询方式 LHS and RHS
为了进一步理解,我们需要多介绍一点编译器的术语.编译器在编译过程的第二步中生成了代码,引擎执行它时,会通过查找变量 a 来判断它是否已声明过.查找的过程由作用域进行协助,但是引擎执行怎样的查找,会影响 ...
- jQuery div鼠标移动效果
<head runat="server"> <meta http-equiv="Content-Type" content="tex ...
- python 输入参数解包,模块导入,接收IO输入参数
#coding=utf-8 from sys import argv script,first,second,third = argv print "the script is=" ...