ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

AT2336 [ARC069D] Flags 2-SAT 线段树优化建图

2021-01-16 08:32:37  阅读:137  来源: 互联网

标签:AT2336 ARC069D int pos mid 建图 low ql


题意:

戳这里

分析:

挺裸的一道题,直接二分答案,然后建图跑 \(2-SAT\) 判断合法性

但是会发现复杂度瓶颈在于 \(O(n^2)\) 建图

我们发现每一次连边都是向距离在 \((min,pos_i-mid)\) 和 \((pos_i+mid,max)\) 这段区间内的点连边,然后我们就可以用线段树优化建图来将建图的复杂度降低到 \(O(n\log )\)

tip:

  1. 按照 \(pos\) 为关键字对点进行升序排序,建图的时候,每个叶子结点向自己的对应点连一条边,这样连边方式变成了向一段区间内连边,但是一定要少掉自己,即向 \((pos_i-mid,pos_i)\) 和 \((pos_i+1,pos_i+mid)\) 区间连边
  2. 由于每次 \(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. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有