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 Twisted架构英文版

    原作出处:twisted-intro 作者:Dave 转载声明:版权归原作出处所有,转载只为让更多人看到这部优秀作品合集,如果侵权,请留言告知 Twisted Introduction This mu ...

  2. MongDB安装使用

    4.MongoDB 下载 MongoDB 提供了可用于 32 位和 64 位系统的预编译二进制包,你可以从MongoDB官网下载安装,MongoDB 预编译二进制包下载地址:https://www.m ...

  3. leetcode696

    本题先寻找字符串中0变1,或者1变0的位置作为分隔位置.然后从这个分隔位置同时向左.右两侧搜索. 找到的左连续串和右连续串,都进行累计. public class Solution { public ...

  4. CBV中的dispatch

    之前介绍了FBV和CBV ,下面我们看一下CBV中的dispatch dispatch函数在类View中定义,作用就是通过反射查找get或post函数,所以在执行get或post函数之前,dispat ...

  5. XML文件中“>”和“<”的转码

    在xml文件中,大于号“>”和小于号“<”是不能被直接识别的,需要经过转码才可以被识别,转码后的格式如下: < < 小于 > > 大于

  6. pandas中DataFrame相关

    1.创建 1.1  标准格式创建 DataFrame创建方法有很多,常用基本格式是:DataFrame 构造器参数:DataFrame(data=[],index=[],coloumns=[]) In ...

  7. Python将两个数组合并成一个数组,多维数组变成一维数组

    1.extend方法 c1 = ["Red","Green","Blue"] c2 = ["Orange"," ...

  8. codeforce 460DIV2 D题

    感觉这个题不错,对拓扑排序有了更深的了解,用两种拓扑排序都写了些试试. dfs #include <cstdio> #include <algorithm> #include ...

  9. SpringBoot26 利用 Ribbon + RestTemplate 调用远程服务资源

    1 RestTemplate扫盲 借助 RestTemplate,Spring应用能够方便地使用REST资源  2 准备 创建三个springCloud项目 >Eureaka : 服务注册中心 ...

  10. Docker学习笔记_删除某个镜像

    实验:删除某个镜像 sudo docker rmi [Image ID] 1.查看镜像的ID                  sudo docker images 2.删除镜像            ...