_bzoj1007 [HNOI2008]水平可见直线【单调栈】

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1007

按斜率排序,去掉斜率相同时,截距较小的直线(即只保留该斜率下截距最大的直线)。若当前直线与栈顶直线的交点的x坐标<=栈顶直线与栈顶第二条直线的交点的x左边,则pop,直到前者大于后者为止,因为若小于等于,那么栈顶这条直线一定被覆盖。

#include <cstdio>
#include <algorithm>

const int maxn = 50005;

int n, tem_n, top, ori_n;
char book[maxn];
struct line {
	long long k, b;
	int id;
} a[maxn], stk[maxn];
struct point {
	double x, y;
};

bool cmp(const line & aa, const line & ss) {
	if (aa.k == ss.k) {
		return aa.b > ss.b;
	}
	return aa.k < ss.k;
}

int main(void) {
	scanf("%d", &n);
	for (int i = 0; i < n; ++i) {
		scanf("%lld%lld", &a[i].k, &a[i].b);
		a[i].id = i;
	}
	std::sort(a, a + n, cmp);
	tem_n = 1;
	for (int i = 1; i < n; ++i) {
		if (a[i].k != a[i - 1].k) {
			a[tem_n++] = a[i];
		}
	}
	ori_n = n;
	n = tem_n;
	
	for (int i = 0; i < n; ++i) {
		while (top > 1 && (stk[top - 1].b - a[i].b) * (stk[top - 1].k - stk[top - 2].k) <= (stk[top - 2].b - stk[top - 1].b) * (a[i].k - stk[top - 1].k)) {
			--top;
		}
		stk[top++] = a[i];
	}
	for (int i = 0; i < top; ++i) {
		book[stk[i].id] = 1;
	}
	for (int i = 0; i < ori_n; ++i) {
		if (book[i]) {
			printf("%d ", i + 1);
		}
	}
	return 0;
}

  

posted @ 2016-12-14 20:41  ciao_sora  阅读(250)  评论(0编辑  收藏  举报