【BZOJ3190】【JLOI2013】赛车

【题目链接】

【思路要点】

  • 补档博客,无题解。

【代码】

#include<bits/stdc++.h>
using namespace std;
#define MAXN	50005
#define INF	1e15
#define EPS	1e-18
#define FPS	1e-15
#define LPS	1e-13
struct point {long double x, y; };
struct line {point a, b; long double k; int home; };
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; }
bool equal(point a, point b) {return equal(a.x, b.x) && equal(a.y, b.y); }
bool equal(line a, line b) {return equal(a.a, b.a) && equal(a.b, b.b); }
bool parallel(line x, line y) {return equal((x.b - x.a) * (y.b - y.a), 0); }
bool operator < (line a, line b) {return a.k < b.k; }
point intersect(line x, line y) {
	long double u = (x.b - x.a) * (y.a - x.a);
	long double v = (x.a - x.b) * (y.b - x.a);
	return (y.a * v + y.b * u) * (1 / (u + v));
}
bool func(line a, line b, line c) {
	point tmp = intersect(a, b);
	return (c.b - c.a) * (tmp - c.a) < -EPS;
}
long double k[MAXN], v[MAXN];
line a[MAXN], q[MAXN];
vector <int> home[MAXN];
bool ans[MAXN];
int main() {
	int n; cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> k[i];
	for (int i = 1; i <= n; i++)
		cin >> v[i];
	int total = 0;
	total++;
	a[total].a = (point) {-FPS, 1};
	a[total].b = (point) {-FPS, 0};
	a[total].k = Polar_angle(a[total].b - a[total].a);
	a[total].home = 0;
	for (int i = 1; i <= n; i++) {
		total++;
		a[total].a = (point) {0, k[i]};
		a[total].b = (point) {1, k[i] + v[i]};
		a[total].k = Polar_angle(a[total].b - a[total].a);
		a[total].home = i;
	}
	sort(a + 1, a + total + 1);
	int top = 1;
	q[top] = a[1];
	home[top].push_back(a[1].home);
	for (int i = 2; i <= total; i++) {
		while (top >= 2 && func(q[top - 1], q[top], a[i])) top--;
		q[++top] = a[i];
		home[top].clear();
		home[top].push_back(a[i].home);
		if (parallel(q[top], q[top - 1])) {
			top--;
			if (equal(q[top], a[i])) home[top].push_back(a[i].home);
		}
	}
	for (int i = 1; i <= top; i++)
		for (unsigned j = 0; j < home[i].size(); j++)
			ans[home[i][j]] = true;
	int tot = 0;
	for (int i = 1; i <= n; i++)
		tot += ans[i];
	bool printed = false;
	cout << tot << endl;
	for (int i = 1; i <= n; i++)
		if (ans[i]) if (printed) cout << ' ' << i;
		else {cout << i; printed = true; }
	cout << endl;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值