【BZOJ2732】【HNOI2012】射箭

【题目链接】

【思路要点】

  • 补档博客,无题解。

【代码】

#include<bits/stdc++.h>
using namespace std;
#define MAXN	300005
#define INF	1e15
#define EPS	1e-18
#define QPS	1e-15
#define LPS	1e-13
#define PI	acos(-1)
struct point {long double x, y; };
struct line {point a, b; long double k; };
point operator - (point a, point b) {return (point) {a.x - b.x, a.y - b.y}; }
point operator + (point a, point b) {return (point) {a.x + b.x, a.y + b.y}; }
point operator * (point a, long double b) {return (point) {a.x * b, a.y * b}; }
long double operator * (point a, point b) {return a.x * b.y - a.y * b.x; }
long double Polar_Angle(point a) {return atan2(a.y, a.x); }
bool equal(long double a, long double b) {return fabs(a - b) < EPS; }
point intersect(line x, line y) {
	long double u = (x.a - x.b) * (y.a - x.b);
	long double v = (x.b - x.a) * (y.b - x.b);
	return (y.a * v + y.b * u) * (1 / (u + v));
}
int n;
long double x[MAXN], yI[MAXN], yII[MAXN];
line a[MAXN];
point getpoint(long double x, long double y, long double z) {
	long double ty = y / x - z * x;
	return (point) {z, ty};
}
bool cmp(line x, line y) {
	return x.k < y.k;
}
bool onright(line x, point y) {
	return (x.b - x.a) * (y - x.a) < EPS;
}
bool check(int n) {
	int cnt = 0;
	cnt++;
	a[cnt].a = (point) {-INF, INF};
	a[cnt].b = (point) {-INF, LPS};
	a[cnt].k = Polar_Angle(a[cnt].b - a[cnt].a);
	cnt++;
	a[cnt].a = (point) {-INF, LPS};
	a[cnt].b = (point) {-LPS, LPS};
	a[cnt].k = Polar_Angle(a[cnt].b - a[cnt].a);
	cnt++;
	a[cnt].a = (point) {-LPS, LPS};
	a[cnt].b = (point) {-LPS, INF};
	a[cnt].k = Polar_Angle(a[cnt].b - a[cnt].a);
	cnt++;
	a[cnt].a = (point) {-LPS, INF};
	a[cnt].b = (point) {-INF, INF};
	a[cnt].k = Polar_Angle(a[cnt].b - a[cnt].a);
	for (int i = 1; i <= n; i++) {
		cnt++;
		a[cnt].a = getpoint(x[i], yI[i], 0);
		a[cnt].b = getpoint(x[i], yI[i], 1);
		a[cnt].k = Polar_Angle(a[cnt].b - a[cnt].a);
		cnt++;
		a[cnt].a = getpoint(x[i], yII[i], 1);
		a[cnt].b = getpoint(x[i], yII[i], 0);
		a[cnt].k = Polar_Angle(a[cnt].b - a[cnt].a);
	}
	sort(a + 1, a + cnt + 1, cmp);
	static line q[MAXN];
	static point p[MAXN];
	int l = 1, r = 1;
	q[1] = a[1];
	for (int i = 2; i <= cnt; i++) {
		while (l < r && onright(a[i], p[r - 1])) r--;
		while (l < r && onright(a[i], p[l])) l++;
		q[++r] = a[i];
		if (equal(0, (q[r].b - q[r].a) * (q[r - 1].b - q[r - 1].a))) {
			r--;
			if ((q[r].b - q[r].a) * (a[i].b - q[r].a) > 0) q[r] = a[i];
		}
		if (r > l) p[r - 1] = intersect(q[r - 1], q[r]);
		if (q[r].k - q[r - 1].k >= PI) return false;
	}
	while (l < r && onright(q[l], p[r - 1])) r--;
	while (l < r && onright(q[r], p[l])) l++;
	return r - l >= 2;
}
int main() {
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
		scanf("%Lf%Lf%Lf", &x[i], &yI[i], &yII[i]);
		yI[i] -= QPS; yII[i] += QPS;
	}
	int l = 1, r = n;
	while (l < r) {
		int mid = (l + r + 1) / 2;
		if (check(mid)) l = mid;
		else r = mid - 1;
	}
	cout << l << endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39972971/article/details/80052406