zoukankan      html  css  js  c++  java
  • bzoj 1007[HNOI2008]水平可见直线 半平面交

    1007: [HNOI2008]水平可见直线

    Time Limit: 1 Sec  Memory Limit: 162 MB

    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

    可以想象最终在上面的图形是一个半凸包
    所以只需要按照斜率排序
    将前面的直线都推到一个栈里
    如果新加入的直线和栈顶直线交点在之前交点的左面
    那么凸包栈顶的直线就被覆盖了,弹出就可以了

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #define LL long long
     6 
     7 using namespace std;
     8 
     9 const int MAXN = 5e4 + 10;
    10 
    11 int N;
    12 int top = 0;
    13 int ans[MAXN];
    14 int sta[MAXN];
    15 double x[MAXN];
    16 
    17 struct line {
    18     double k;
    19     double b;
    20     int id;
    21 } l[MAXN];
    22 
    23 bool cmp(line a, line b)
    24 {
    25     if(a.k == b.k) {
    26         return a.b > b.b;
    27     }
    28     return a.k < b.k;
    29 }
    30 
    31 inline LL read()
    32 {
    33     LL x = 0, w = 1; char ch = 0;
    34     while(ch < '0' || ch > '9') {
    35         if(ch == '-') {
    36             w = -1;
    37         }
    38         ch = getchar();
    39     }
    40     while(ch >= '0' && ch <= '9') {
    41         x = x * 10 + ch - '0';
    42         ch = getchar();
    43     }
    44     return x * w;
    45 }
    46 
    47 double intersaction(int a, int b)
    48 {
    49     return (l[b].b - l[a].b) / (l[a].k - l[b].k);
    50 }
    51 int main()
    52 {
    53     N = read();
    54     for(int i = 1; i <= N; i++) {
    55         scanf("%lf%lf", &l[i].k, &l[i].b);
    56         l[i].id = i;
    57     }
    58     sort(l + 1, l + N + 1, cmp);
    59     sta[0] = 1;
    60     top = 1;
    61     for(int i = 2; i <= N; i++) {
    62         if(l[i].k == l[sta[top - 1]].k) {
    63             continue;
    64         }
    65         while(intersaction(i, sta[top - 1]) <= intersaction(sta[top - 1], sta[top - 2]) && top > 1) {
    66             top--;
    67         }
    68         top++;
    69         sta[top - 1] = i;
    70     }
    71     for(int i = 0; i < top; i++) {
    72         ans[l[sta[i]].id] = 1;
    73     }
    74     for(int i = 1; i <= N; i++) {
    75         if(ans[i]) {
    76             printf("%d ", i);
    77         }
    78     }
    79     return 0;
    80 }
    View Code
  • 相关阅读:
    Ajax 学习笔记
    StringBulider简单用法
    asp.net 发送邮件
    log4net日志组件
    Web.Config文件详解
    关闭discuzX3.2注册页面的注册邮箱验证
    Oracle 序列(sequence)的创建、修改及删除
    MySQL 和 Oracle 主键自增长
    EL(表达式)语言的几种运算符
    SQL:select case when 的用法
  • 原文地址:https://www.cnblogs.com/wuenze/p/8387811.html
Copyright © 2011-2022 走看看