半平面交O(n)判断

先放在这里,本来是要写CF549E的但是正解不是这个

O(n)判断半平面交

判断面积>=0

随机打乱顺序,依次加进去同时维护一个在半平面交内且y最小的点

如果点不在新加的半平面内就对和之前的半平面暴力求交点,在剩下的区间上取y最小的

交出来区间为空就不存在

看起来很玄,考虑时间复杂度

对于当前加的第i条边,需要修改的情况当且仅当第i条边是1~i条边组成的半平面中最下面的两条之一,由于随机打乱了所以期望是2/i

那么时间就是\(\sum \frac{2}{i}*O(i)+(1-\frac{2}{i})*O(1)=O(n)\)

有可能当前的半平面没有封底,所以加一条y=-inf即可,实际可以不用加

求交的时候用点积判断(模长*投影长)

代码并没有调出来,也许以后再说

#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define abs(x) ((x)>0?(x):-(x))
#define E 0.000000001
#define ll long long
#define file
using namespace std;

struct point {double x,y;} a[10001],b[10001],p1,p2,P;
struct xl {double X1,Y1,X2,Y2;} c,c2,s1,s2;
int n,m,i,j,k,l,randomseed;

double cj(xl a,xl b) {return (b.X2-b.X1)*(a.Y2-a.Y1)-(a.X2-a.X1)*(b.Y2-b.Y1);};
double dj(xl a,xl b) {return (a.X2-a.X1)*(b.X2-b.X1)+(a.Y2-a.Y1)*(b.Y2-b.Y1);};
point jd(xl a,xl b)
{
	double s1=cj({a.X1,a.Y1,b.X2,b.Y2},a),s2=cj(a,{a.X1,a.Y1,b.X1,b.Y1});
	if (abs(s1+s2)<E) return{-114514,-1919810};
	double s=s2/(s1+s2);
	
	return {b.X1+(b.X2-b.X1)*s,b.Y1+(b.Y2-b.Y1)*s};
}

void work(bool type)
{
	double x=0,y=-114514,m1,m2,s;
	bool bz1=1,bz2=1,bz3=1;
	int i,j,k,l;
	
	random_shuffle(a+1,a+n+1);
	random_shuffle(b+1,b+m+1);
	fo(i,1,n)
	{
		fo(j,1,m)
		if (a[i].x==b[j].x && a[i].y==b[j].y) {printf("NO\n"); exit(0);}
		else
		{
			c={(a[i].x+b[j].x)/2.0,(a[i].y+b[j].y)/2.0};
			if (!type) c.X2=c.X1-(a[i].y-b[j].y),c.Y2=c.Y1+(a[i].x-b[j].x);
			else c.X2=c.X1+(a[i].y-b[j].y),c.Y2=c.Y1-(a[i].x-b[j].x);
			
			if (cj({c.X1,c.Y1,x,y},c)>E)
			{
				p1={c.X1-(c.X2-c.X1)*20000,c.Y1-(c.Y2-c.Y1)*20000};m1=-9223372036854775807ll;
				p2={c.X1+(c.X2-c.X1)*20000,c.Y1+(c.Y2-c.Y1)*20000};m2=9223372036854775807ll;
				
				fo(k,1,i)
				{
					fo(l,1,m)
					if (k==i && l==j) break;
					else
					{
						c2={(a[k].x+b[l].x)/2.0,(a[k].y+b[l].y)/2.0};
						if (!type) c2.X2=c2.X1-(a[k].y-b[l].y),c2.Y2=c2.Y1+(a[k].x-b[l].x);
						else c2.X2=c2.X1+(a[k].y-b[l].y),c2.Y2=c2.Y1-(a[k].x-b[l].x);
						
						P=jd(c,c2);
						if (P.y==-1919810)
						{
							if (cj({c.X1,c.Y1,c2.X1,c2.Y1},c)>E && cj({c2.X1,c2.Y1,c.X1,c.Y1},c2)>E)
							return;
							else
							continue;
						}
						
						if (cj(c,{c.X1,c.Y1,c2.X1,c2.Y1})<cj(c,{c.X1,c.Y1,c2.X2,c2.Y2}))
						{s=dj(c,{c.X1,c.Y1,P.x,P.y});if (s<m2) m2=s,p2=P;}
						else
						{s=dj(c,{c.X1,c.Y1,P.x,P.y});if (s>m1) m1=s,p1=P;}
						if (m1>m2) return;
					}
				}
				if (p1.y<p2.y) x=p1.x,y=p1.y; else x=p2.x,y=p2.y;
			}
		}
	}
	fo(i,1,n)
	{
		fo(j,1,m)
		{
			c={(a[i].x+b[j].x)/2.0,(a[i].y+b[j].y)/2.0};
			if (!type) c.X2=c.X1-(a[i].y-b[j].y),c.Y2=c.Y1+(a[i].x-b[j].x);
			else c.X2=c.X1+(a[i].y-b[j].y),c.Y2=c.Y1-(a[i].x-b[j].x);
			
			s=cj(c,{c.X1,c.Y1,x+0.000001,y+0.000001}),bz1&=s>E;
			s=cj(c,{c.X1,c.Y1,x-0.000001,y+0.000001}),bz2&=s>E;
			s=cj(c,{c.X1,c.Y1,x,y+0.000001}),bz3&=s>E;
			if (!bz1 && !bz2 && !bz3) return;
		}
	}
	printf("YES\n");exit(0);
}

int main()
{
	randomseed=time(NULL);
	srand(randomseed);
	freopen("cf549E.in","r",stdin);
	#ifdef file
	freopen("b.out","w",stdout);
	#endif
//	#ifdef file
//	freopen("cf549E.in","r",stdin);
//	#endif
	
	scanf("%d%d",&n,&m);
	fo(i,1,n) scanf("%lf%lf",&a[i].x,&a[i].y);
	fo(i,1,m) scanf("%lf%lf",&b[i].x,&b[i].y);
	
	work(0);work(1);
	printf("NO\n");
	
	fclose(stdin);
	fclose(stdout);
	return 0;
}

参考资料

https://wenku.baidu.com/view/9097ccd549649b6648d74712.html

https://wenku.baidu.com/view/a836ff44ad02de80d4d84095.html

posted @ 2020-05-19 12:21  gmh77  阅读(393)  评论(0编辑  收藏  举报