1007: [HNOI2008]水平可见直线
思路:简单数学+计算几何
按斜率将直线排序
将每一条直线压入栈中
每次入栈时判断栈顶的后一个节点与当前直线是否覆盖掉栈顶直线
若覆盖则弹出
代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;
const int MAXN=50010;
typedef long long ull;
#define x first
#define y second
#define LINE pair<pair<ull,ull>,ull>
LINE line[MAXN],stack[MAXN];
int n,top;
bool work[MAXN];
bool cover(LINE A,LINE B,LINE C)
{
if (C.x.x==B.x.x) return true;
if ((C.x.y-B.x.y)*(A.x.x-C.x.x)<=(C.x.y-A.x.y)*(B.x.x-C.x.x)) return true;
return false;
}
void init()
{
cin>>n;
for (int i=1;i<=n;i++) {
scanf("%lld%lld",&line[i].x.x,&line[i].x.y);
line[i].y=i; }
sort(line+1,line+n+1);
for (int i=1;i<=n;i++) {
while ((top && stack[top].x.x==line[i].x.x) || (top>=2 && cover(stack[top-1],stack[top],line[i])))
top--;
stack[++top]=line[i]; }
for (int i=1;i<=top;i++)
work[stack[i].y]=true;
for (int i=1;i<=n;i++)
if (work[i])
printf("%d ",i);
return ;
}
int main()
{
init();
return 0;
}