CF429E Points and Segments

首先这个限制他有单点有线段,不是很整,通过轻微调整,把单点调整为一个区间,换个说法就是把端点强行定义一个偏序使得和原题限制不变,即如果位置相同,钦定左端点小于右端点。

这样的话,整条直线被划分为了\(2n+1\)段区间,每段区间受一些限制。发现这些区间依次向右,受影响的线段只多/少了一个。那么就是每段区间受影响的线段个数分别为奇数,偶数,奇数,偶数。那么对偶数的限制即为红色和蓝色个数必须相等,对奇数可以直接不考虑,因为相邻的两个偶数限制区间都符合题意的话,那么这个奇数区间一定符合红色和蓝色差不超过\(1\)。这步是真的神sto sjw orz。

接下来就考虑每次变化的两个线段,如果一个是左端点一个是右端点,那么这两条线段的颜色必须一样,否则必须不一样。按照如此限制跑个2-sat即可。时间复杂度为排序的\(O(n\log n)\)

接下来证明这个方程组一定有解。每个未知数\(x_i\)在这个方程组里只会出现\(2\)次。那么把每个方程里的两个未知数连边的话一定是一堆环的形式。考虑把每个环的这些方程加起来,你会得到\(0=0\),也就是说这些方程里面有一个是多余的。把随便一个去掉,给了一个限制,剩下的是一条链,按着拓扑序构造一定可以构造出解。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<stack>
using namespace std;
typedef long long ll;
#define N 200002
struct node{int x,id,op;}a[N];
struct edge{int to,nxxt;}e[N<<3];
int n,tot,js,head[N<<2],cnt=2,dfn[N],low[N],f[N],cn,an;
bool inq[N];
stack<int>s;
inline void ins(int u,int v){e[cnt]=(edge){v,head[u]};head[u]=cnt++;}
inline bool cmp(node n1,node n2)
{
	if(n1.x^n2.x)return n1.x<n2.x;
	else return n1.op>n2.op;
}
void tarjan(int x)
{dfn[x]=low[x]=++cn;inq[x]=1;s.push(x);
	for(int i=head[x];i;i=e[i].nxxt)
	{int j=e[i].to;
		if(!dfn[j])tarjan(j),low[x]=min(low[x],low[j]);
		else if(inq[j])low[x]=min(low[x],dfn[j]);
	}
	if(dfn[x]==low[x])
	{an++;
		while(!s.empty()&&s.top()!=x){inq[s.top()]=0;f[s.top()]=an;s.pop();}
		inq[x]=0;f[x]=an;s.pop();
	}
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		int x,y;scanf("%d%d",&x,&y);
		a[++tot]=(node){x,i,1};a[++tot]=(node){y,i,-1};
	}
	sort(a+1,a+1+tot,cmp);int su=0;
	for(int i=2;i<=tot;i+=2)
	{
		if(a[i].op!=a[i-1].op)
		{
			ins(a[i].id,a[i-1].id);ins(a[i-1].id,a[i].id);
			ins(a[i].id+n,a[i-1].id+n);ins(a[i-1].id+n,a[i].id+n);
		}
		else
		{
			ins(a[i].id,a[i-1].id+n);ins(a[i].id+n,a[i-1].id);
			ins(a[i-1].id,a[i].id+n);ins(a[i-1].id+n,a[i].id);
		}
	}
	for(int i=1;i<=2*n;i++)if(!dfn[i])tarjan(i);
	for(int i=1;i<=n;i++)printf("%d ",f[i]<f[i+n]);puts("");
}

posted @ 2021-03-01 20:33  Lebron_Durant  阅读(103)  评论(0)    收藏  举报