1. 程式人生 > >BZOJ5317 JSOI2018部落戰爭(凸包)

BZOJ5317 JSOI2018部落戰爭(凸包)

凸包 define zoj 直接 存在 ons print nbsp names

  即詢問凸包是否有交。這顯然可以直接求半平面交,但是復雜度O(q(n+m)),且沒有什麽優化空間。

  更直接地表示,即相當於詢問是否存在點a∈A,b∈B,使得a+d=b。移項,得到d=b-a。可以發現等式右邊是一個閔可夫斯基和。求閔可夫斯基和只需要分別求出兩個凸包,然後每次考慮ai+1+bi和ai+bi+1哪個將作為凸包中下一個點。將其求出後,只需要判斷點是否在凸包內。二分找到上下邊界即可。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include
<cstring> #include<algorithm> #include<cassert> using namespace std; #define ll long long #define vector point #define N 200010 int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<0||c>9) {if (c==-) f=-1;c=getchar();}
while (c>=0&&c<=9) x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,m,q; const double eps=1E-8; struct point { int x,y; vector operator +(const vector&a) const { return (vector){x+a.x,y+a.y}; } vector operator -(const vector&a) const
{ return (vector){x-a.x,y-a.y}; } ll operator *(const vector&a) const { return 1ll*x*a.y-1ll*y*a.x; } bool operator <(const point&a) const { return x<a.x||x==a.x&&y<a.y; } }a[N],b[N],c[N],d[N],e[N],f[N]; struct line { point a;vector p; double f(int x){return a.y+(double)(x-a.x)/p.x*p.y;} }; void makehull(point *hull,point *a,int &n) { sort(a+1,a+n+1);hull[1]=a[1]; int m=1; for (int i=2;i<=n;i++) { while (m>1&&(a[i]-hull[m-1])*(hull[m]-hull[m-1])>0) m--; hull[++m]=a[i]; } for (int i=n-1;i>=1;i--) { while (m>1&&(a[i]-hull[m-1])*(hull[m]-hull[m-1])>0) m--; hull[++m]=a[i]; } n=m; } void merge(point *up,point *down,point *a,point *b,int &n,int &m) { int p=1,u=1,v=1;up[1]=a[1]+b[1]; while (u<n||v<m) { if (u==n) v++; else if (v==m) u++; else if ((a[u+1]+b[v]-up[p])*(a[u]+b[v+1]-up[p])>0) u++;else v++; while (p>1&&(a[u]+b[v]-up[p-1])*(up[p]-up[p-1])>0) p--; up[++p]=a[u]+b[v]; } for (int i=1;i<=p;i++) if (up[i].x>up[i+1].x) {n=i;break;} for (int i=n;i<=p;i++) down[i-n+1]=up[i];m=p-n+1; } int main() { #ifndef ONLINE_JUDGE freopen("bzoj5317.in","r",stdin); freopen("bzoj5317.out","w",stdout); #endif n=read(),m=read(),q=read(); for (int i=1;i<=n;i++) a[i].x=read(),a[i].y=read(); for (int i=1;i<=m;i++) b[i].x=-read(),b[i].y=-read(); makehull(c,a,n),makehull(d,b,m); merge(e,f,c,d,n,m);reverse(f+1,f+m+1); for (int i=1;i<=q;i++) { int x=read(),y=read(); int u=lower_bound(e+1,e+n+1,(point){x,y})-e; if (u==1||u==n+1||(line){e[u-1],e[u]-e[u-1]}.f(x)-eps>y) {printf("0\n");continue;} u=lower_bound(f+1,f+m+1,(point){x,y})-f; if (u==1||u==m+1||(line){f[u-1],f[u]-f[u-1]}.f(x)+eps<y) {printf("0\n");continue;} printf("1\n"); } return 0; }

BZOJ5317 JSOI2018部落戰爭(凸包)