标签:AT2336 ARC069D int pos mid 建图 low ql
题意:
分析:
挺裸的一道题,直接二分答案,然后建图跑 \(2-SAT\) 判断合法性
但是会发现复杂度瓶颈在于 \(O(n^2)\) 建图
我们发现每一次连边都是向距离在 \((min,pos_i-mid)\) 和 \((pos_i+mid,max)\) 这段区间内的点连边,然后我们就可以用线段树优化建图来将建图的复杂度降低到 \(O(n\log )\)
tip:
- 按照 \(pos\) 为关键字对点进行升序排序,建图的时候,每个叶子结点向自己的对应点连一条边,这样连边方式变成了向一段区间内连边,但是一定要少掉自己,即向 \((pos_i-mid,pos_i)\) 和 \((pos_i+1,pos_i+mid)\) 区间连边
- 由于每次 \(check\) 会清空 \(head\) 数组,所以会将建出来的线段树也清掉,所以每次记得重建一次
代码:
#include<bits/stdc++.h>
#define pii pair<int,int>
#define mk(x,y) make_pair(x,y)
#define lc rt<<1
#define rc rt<<1|1
#define pb push_back
#define fir first
#define sec second
#define inl inline
#define reg register
using namespace std;
namespace zzc
{
inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
const int maxn = 2e5+5;
int n,m,top,col,tim,idx,cnt;
int id[maxn],head[maxn],bel[maxn],dfn[maxn],low[maxn],st[maxn];
bool vis[maxn];
struct edge
{
int to,nxt;
}e[maxn<<3];
void add(int u,int v)
{
e[++cnt].to=v;
e[cnt].nxt=head[u];
head[u]=cnt;
}
struct node
{
int pos,id;
node(){}
node(int pos,int id=0):pos(pos),id(id){}
bool operator <(const node &b)const
{
return pos<b.pos;
}
}p[maxn];
int op(int x)
{
return x<=n?x+n:x-n;
}
void build(int rt,int l,int r)
{
id[rt]=++idx;
if(l==r)
{
add(id[rt],op(p[l].id));
return ;
}
int mid=(l+r)>>1;
build(lc,l,mid);build(rc,mid+1,r);
add(id[rt],id[lc]);add(id[rt],id[rc]);
}
void link(int rt,int l,int r,int ql,int qr,int x)
{
if(ql>qr) return ;
if(ql<=l&&r<=qr)
{
add(x,id[rt]);
return ;
}
int mid=(l+r)>>1;
if(ql<=mid) link(lc,l,mid,ql,qr,x);
if(qr>mid) link(rc,mid+1,r,ql,qr,x);
}
void tarjan(int u)
{
dfn[u]=low[u]=++tim;
st[++top]=u;
vis[u]=true;
for(int i=head[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(vis[v]) low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u])
{
col++;
do
{
bel[st[top]]=col;
vis[st[top]]=false;
}while(st[top--]!=u);
}
}
bool check(int x)
{
for(int i=1;i<=idx;i++) head[i]=0,dfn[i]=0;
cnt=0;tim=0;top=0;
build(1,1,idx=2*n);
for(int i=1;i<=2*n;i++)
{
int l=upper_bound(p+1,p+2*n+1,node(p[i].pos-x))-p;
int r=upper_bound(p+1,p+2*n+1,node(p[i].pos+x-1))-p-1;
link(1,1,2*n,l,i-1,p[i].id);link(1,1,2*n,i+1,r,p[i].id);
}
for(int i=1;i<=2*n;i++) if(!dfn[i]) tarjan(i);
for(int i=1;i<=n;i++) if(bel[i]==bel[i+n]) return false;
return true;
}
void work()
{
n=read();
for(int i=1;i<=n;i++)
{
p[i].pos=read();p[i+n].pos=read();
p[i].id=i;p[i+n].id=i+n;
}
sort(p+1,p+2*n+1);
int l=0,r=p[2*n].pos-p[1].pos+1,mid,ans;
while(l<=r)
{
mid=(l+r)>>1;
if(check(mid))
{
ans=mid;
l=mid+1;
}
else r=mid-1;
}
printf("%d\n",ans);
}
}
int main()
{
zzc::work();
return 0;
}
标签:AT2336,ARC069D,int,pos,mid,建图,low,ql 来源: https://www.cnblogs.com/youth518/p/14284913.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。