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+线段树优化建图+二分的更多相关文章

  1. 2-sat 问题 【例题 Flags(2-sat+线段树优化建图)】

    序: 模拟赛考了一道 2-sat 问题.之前从来没听过…… 考完才发现其实这个东东只要一个小小的 tarjan 求强连通分量就搞定了. 这个方法真是巧妙啊,拿来讲讲. What is it? [・_・ ...

  2. BZOJ5017 [SNOI2017]炸弹 - 线段树优化建图+Tarjan

    Solution 一个点向一个区间内的所有点连边, 可以用线段树优化建图来优化 : 前置技能传送门 然后就得到一个有向图, 一个联通块内的炸弹可以互相引爆, 所以进行缩点变成$DAG$ 然后拓扑排序. ...

  3. 【BZOJ3681】Arietta 树链剖分+可持久化线段树优化建图+网络流

    [BZOJ3681]Arietta Description Arietta 的命运与她的妹妹不同,在她的妹妹已经走进学院的时候,她仍然留在山村中.但是她从未停止过和恋人 Velding 的书信往来.一 ...

  4. 【bzoj5017】[Snoi2017]炸弹 线段树优化建图+Tarjan+拓扑排序

    题目描述 在一条直线上有 N 个炸弹,每个炸弹的坐标是 Xi,爆炸半径是 Ri,当一个炸弹爆炸时,如果另一个炸弹所在位置 Xj 满足:  Xi−Ri≤Xj≤Xi+Ri,那么,该炸弹也会被引爆.  现在 ...

  5. 【bzoj4699】树上的最短路(树剖+线段树优化建图)

    题意 给你一棵 $n$ 个点 $n-1$ 条边的树,每条边有一个通过时间.此外有 $m$ 个传送条件 $(x_1,y_1,x_2,y_2,c)$,表示从 $x_1$ 到 $x_2$ 的简单路径上的点可 ...

  6. 【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 ...

  7. 【bzoj3073】[Pa2011]Journeys 线段树优化建图+堆优化Dijkstra

    题目描述 Seter建造了一个很大的星球,他准备建造N个国家和无数双向道路.N个国家很快建造好了,用1..N编号,但是他发现道路实在太多了,他要一条条建简直是不可能的!于是他以如下方式建造道路:(a, ...

  8. 【bzoj4383】[POI2015]Pustynia 线段树优化建图+差分约束系统+拓扑排序

    题目描述 给定一个长度为n的正整数序列a,每个数都在1到10^9范围内,告诉你其中s个数,并给出m条信息,每条信息包含三个数l,r,k以及接下来k个正整数,表示a[l],a[l+1],...,a[r- ...

  9. 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 ...

随机推荐

  1. python arp欺骗

    使用python构造一个arp欺骗脚本 import os import sys from scapy.all import * import optparse def main(): usage=& ...

  2. PHP安装使用Zend Opcache扩展

    简介 Zend OPCache 的前身是Zend Optimizer + (Zend O+),于 2013年3月中旬改名为 Opcache.其通过 opcode 缓存和优化提供更快的 PHP 执行过程 ...

  3. Python 约束 , 自定义异常 , 加密 , 日志

    约束 约束 , 约束其派生类:  保证派生类中必须编写send方法 , 不然执行可能就会报错 Python中  语法: class BaseMessage(object): def send(self ...

  4. VxWorks多任务功能

    http://blog.chinaunix.net/uid-23741326-id-84935.html VxWorks的任务有优先级的概念,其任务调度也是基于优先级考虑的,是抢占式的,VxWorks ...

  5. JavaScript 18岁生日快乐

    12月4日是JS的18岁生日,18年前这个日子JavaScript由Netscape和Sun联合宣布推出.那个星期,Ruby也将推出其第一个版本. 今天Netscape和Sun都已经不在了,但是JS还 ...

  6. Ubuntu 17.04 允许使用root ssh登录

    用ubuntu 17.04部署完docker后,用winscp去管理系统上的文件发现默认的管理员账号权限不够,想重新用root登录,发现一只被服务器拒绝(permission denied).已经执行 ...

  7. const的作用

    const的作用 const是C语言的一种关键字,起受保护,防止以外的变动的作用!可以修饰变量,参数,返回值,甚至函数体.const可以提高程序的健壮性,你只管用到你想用的任何地方. (一)const ...

  8. Bootstrap 简介(Web前端CSS框架)

    目录1.简介2.特点3.组件4.Javascript插件5.定制自己的框架代码6.Bootstrap Less 1.简介Bootstrap是Twitter推出的一个开源的用于前端开发的工具包.它由Tw ...

  9. Sprite Editor

    [Sprite Editor] 在Unity3D中,一个图片可以有多种类型(如下图).对于2D游戏开发,最常用的类型就是Sprite. 下图是Sprite Texture的属性,Packing Tag ...

  10. 面试题:hibernate 有用

    1. Hibernate的工作流程? 答案: 1.通过Configuration对象读取并解析配置文件 2.读取并解析映射信息,创建SessionFactory对象 3.打开session 4.创建事 ...