uoj #242【UR #16】破坏蛋糕

uoj

考虑把那最后一条直线拎出来,并且旋转到和\(y\)轴平行(其他直线同时一起旋转),然后它和其他直线相交形成\(n+1\)个区间,现在要知道这些区间是否处在一个面积有限的区域

可以发现一段在有限区域当且仅当区间的两侧区域都是有限的.所以对线的两侧分开考虑,先考虑左边,如果直线的一个区间旁边的区域有限,那么一定可以找到区间上面一条直线和下面一条直线在所求直线的左侧有交点,这要满足上面直线的斜率大于下面直线,并且他们能覆盖这两条直线与所求直线的交点形成的区间,使得一些连续段区间的左侧为有限区域,那么可以对其他直线从下往上加入,每加入一条直线就找到最下面的并且斜率小于他的直线,然后把对应交点形成的区间覆盖,这些直线可以单调栈维护,区间覆盖可以差分解决.右边同理,把大于小于反过来就行.最后看每一段是否在两边都被覆盖即可

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<cmath>
#include<ctime>
#include<queue>
#include<map>
#include<set>
#define LL long long
#define db double

using namespace std;
const int N=1e5+10;
const db pi=acos(-1),eps=1e-10;
int rd()
{
    int x=0,w=1;char ch=0;
    while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*w;
}
struct point
{
	db x,y;
	point(){}
	point(db nx,db ny){x=nx,y=ny;}
	void rot(db cta)
	{
		db xx=x,yy=y;
		x=cos(cta)*xx-sin(cta)*yy,y=cos(cta)*yy+sin(cta)*xx;
	}
	point operator - (const point &bb) const {return point(x-bb.x,y-bb.y);}
	db operator * (const point &bb) const {return x*bb.y-y*bb.x;}
}a[N][2];
struct line
{
	db k,b;
	line(){}
	line(point xx,point yy)
	{
		k=(xx.y-yy.y)/(xx.x-yy.x);
		b=xx.y-k*xx.x;
	}
	bool operator < (const line &bb) const {return b<bb.b;}
}b[N];
int n,cf[N],c2[N],st[N],tp,an[N],ta;

int main()
{
	n=rd();
	for(int i=1;i<=n+1;++i)
	{
		int x=rd(),y=rd();
		a[i][0]=point(x,y);
		x=rd(),y=rd();
		a[i][1]=point(x,y);
	}
	if(a[n+1][0].x>a[n+1][1].x) swap(a[n+1][0],a[n+1][1]);
	point dtp(a[n+1][0].x,a[n+1][0].y);
	for(int i=1;i<=n+1;++i)
		a[i][0]=a[i][0]-dtp,a[i][1]=a[i][1]-dtp;
	db cta=pi/2-atan2(a[n+1][1].y,a[n+1][1].x);
	for(int i=1;i<=n+1;++i)
		a[i][0].rot(cta),a[i][1].rot(cta);
	for(int i=1;i<=n;++i)
		b[i]=line(a[i][0],a[i][1]);
	sort(b+1,b+n+1);
	tp=0;
	for(int i=1;i<=n;++i)
	{
		int l=1,r=tp,z=0;
		while(l<=r)
		{
			int mid=(l+r)>>1;
			if(b[st[mid]].k<b[i].k-eps) z=mid,r=mid-1;
			else l=mid+1;
		}
		if(z) ++cf[st[z]],--cf[i];
		if(!tp||b[st[tp]].k>b[i].k+eps) st[++tp]=i;
	}
	tp=0;
	for(int i=1;i<=n;++i)
	{
		int l=1,r=tp,z=0;
		while(l<=r)
		{
			int mid=(l+r)>>1;
			if(b[st[mid]].k>b[i].k+eps) z=mid,r=mid-1;
			else l=mid+1;
		}
		if(z) ++c2[st[z]],--c2[i];
		if(!tp||b[st[tp]].k<b[i].k-eps) st[++tp]=i;
	}
	an[++ta]=0;
	for(int i=1;i<n;++i)
	{
		cf[i]+=cf[i-1],c2[i]+=c2[i-1];
		an[++ta]=cf[i]>0&&c2[i]>0;
	}
	an[++ta]=0;
	for(int i=1;i<=ta;++i) printf("%d",an[i]);
    return 0;
}
posted @ 2019-07-11 21:49  ✡smy✡  阅读(165)  评论(0编辑  收藏  举报