_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; }