BZOJ-2732 [HNOI2012]射箭
依旧转成不等式组,然后半平面交。
#include <cstdlib> #include <cstdio> #include <cmath> #include <cstring> #include <cctype> #include <algorithm> #define rep(i, l, r) for(int i=l; i<=r; i++) #define clr(x, c) memset(x, c, sizeof(x)) #define maxn 234567 #define double long double #define linf 1e15 using namespace std; typedef long long ll; inline int read() { int x=0, f=1; char ch=getchar(); while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();} while (isdigit(ch)) x=x*10+ch-'0', ch=getchar(); return x*f; } struct P{double x, y;}; struct line{P a, b; int id; double ang;} l[maxn], a[maxn], q[maxn]; P operator - (P a, P b){return (P){a.x-b.x, a.y-b.y};} double operator * (P a, P b){return a.x*b.y-a.y*b.x;} bool operator < (line a, line b){if (a.ang==b.ang) return (a.b-a.a)*(b.b-b.a)>0; return a.ang<b.ang;} int n, m, L, R, cnt; inline double cal(double a, double b, int x){return b/a-a*x;} P inter(line a, line b) { double k1=(b.b-a.a)*(a.b-a.a), k2=(a.b-a.a)*(b.a-a.a), t=k2/(k1+k2); return (P){b.a.x+t*(b.b.x-b.a.x), b.a.y+t*(b.b.y-b.a.y)}; } bool jud(line a, line b, line t){return (inter(a, b)-t.a)*(t.b-t.a)>0;} void hpi(int x) { int cnt=0; rep(i, 1, m) if (l[i].id<=x) { if (l[i].ang!=a[cnt].ang) cnt++; a[cnt]=l[i]; } L=1, R=0; q[++R]=a[1]; q[++R]=a[2]; rep(i, 3, cnt) { while (L<R && jud(q[R-1], q[R], a[i])) R--; while (L<R && jud(q[L+1], q[L], a[i])) L++; q[++R]=a[i]; } while (L<R && jud(q[R-1], q[R], q[L])) R--; while (L<R && jud(q[L+1], q[L], q[R])) L++; } int main() { n=read(); l[++m].a=(P){-linf, -linf}; l[m].b=(P){linf, -linf}; l[++m].a=(P){linf, -linf}; l[m].b=(P){linf, linf}; l[++m].a=(P){linf, linf}; l[m].b=(P){-linf, linf}; l[++m].a=(P){-linf, linf}; l[m].b=(P){-linf, -linf}; rep(i, 1, n) { double x=read(), ya=read(), yb=read(); l[++m].a.x=-1; l[m].a.y=cal(x, ya, -1); l[m].b.x=1; l[m].b.y=cal(x, ya, 1); l[++m].a.x=1; l[m].a.y=cal(x, yb, 1); l[m].b.x=-1; l[m].b.y=cal(x, yb, -1); l[m].id=l[m-1].id=i; } rep(i, 1, m) l[i].ang=atan2(l[i].b.y-l[i].a.y, l[i].b.x-l[i].a.x); sort(l+1, l+m+1); int l=0, r=n; while (l<r) { int mid=(l+r)>>1; hpi(mid+1); if (R-L>1) l=mid+1; else r=mid; } printf("%d\n", l); return 0; }