Try Again

[HNOI2008]水平可见直线

Description

  在xoy直角坐标平面上有n条直线L1,L2,...Ln,若在y值为正无穷大处往下看,能见到Li的某个子线段,则称Li为
可见的,否则Li为被覆盖的.
例如,对于直线:
L1:y=x; L2:y=-x; L3:y=0
则L1和L2是可见的,L3是被覆盖的.
给出n条直线,表示成y=Ax+B的形式(|A|,|B|<=500000),且n条直线两两不重合.求出所有可见的直线.

Input

  第一行为N(0 < N < 50000),接下来的N行输入Ai,Bi

Output

  从小到大输出可见直线的编号,两两中间用空格隔开,最后一个数字后面也必须有个空格

Sample Input

3
-1 0
1 0
0 0

Sample Output

1 2
先对斜率排序(以从小到大为例)然后逐条判断如图

前四条线符合,判断第五条,算出第五条线与第四条线交点的横坐标X1和第四条线和第三条线交点的横坐标X2,若X1<=X2,说明第四条线被第三条线和第五条线覆盖,删除第四条线,然后向前判断。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
#include <stack>
#include <cstdlib>
#include <iomanip>
#include <cmath>
#include <cassert>
#include <ctime>
#include <cstdlib>
#include <map>
#include <set>
using namespace std;
#pragma comment(linker, "/stck:1024000000,1024000000")
#define lowbit(x) (x&(-x))
#define max(x,y) (x>=y?x:y)
#define min(x,y) (x<=y?x:y)
#define MAX 100000000000000000
#define MOD 1000
#define pi acos(-1.0)
#define ei exp(1)
#define PI 3.1415926535897932384626433832
#define ios() ios::sync_with_stdio(true)
#define INF 1044266558
#define mem(a) (memset(a,0,sizeof(a)))
typedef long long ll;
struct node
{
    int id;
    double k,y;
}e[50006],q[50006];
int n,cnt=0,vis[50006];
bool cmp(node a,node b)
{
    return a.k<b.k || a.k==b.k&&a.y>b.y;
}
double cal(node a,node b)
{
    return (b.y-a.y)/(a.k-b.k);
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        e[i].id=i;
        scanf("%lf%lf",&e[i].k,&e[i].y);
    }
    sort(e+1,e+1+n,cmp);
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=n;i++)
    {
        if(cnt==0) q[++cnt]=e[i];
        else if(e[i].k==q[cnt].k) {vis[e[i].id]=1;continue;}
        else 
        {
            while(1)
            {
                if(cnt==1){q[++cnt]=e[i];break;}
                double x1=cal(e[i],q[cnt]);
                double x2=cal(q[cnt],q[cnt-1]);
                if(x1<=x2) vis[q[cnt].id]=1,cnt--;
                else {q[++cnt]=e[i];break;}
            }
        }
    }
    for(int i=1;i<=n;i++)
    {
        if(!vis[i]) printf("%d ",i);
    }
    return 0;
}

 

posted @ 2018-01-10 16:24  十年换你一句好久不见  阅读(202)  评论(0编辑  收藏  举报