半平面交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;
}