bzoj1007

1007: [HNOI2008]水平可见直线

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 4365  Solved: 1599

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

HINT

Source

题意:题目就很简明

分析:

先按斜率从小到大排列,如果排序后第1,3的直线遮住了第2的直线,那么2,3的交点必定在1,2的交点的左侧,

证明显然,

综上所述,本题得解

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <deque>
 6 #include <vector>
 7 #include <queue>
 8 #include <iostream>
 9 #include <algorithm>
10 #include <map>
11 #include <set>
12 #include <ctime>
13 using namespace std;
14 typedef long long LL;
15 typedef double DB;
16 #define For(i, s, t) for(int i = (s); i <= (t); i++)
17 #define Ford(i, s, t) for(int i = (s); i >= (t); i--)
18 #define MIT (2147483647)
19 #define INF (1000000001)
20 #define MLL (1000000000000000001LL)
21 #define sz(x) ((bnt) (x).size())
22 #define clr(x, y) memset(x, y, sizeof(x))
23 #define puf push_front
24 #define pub push_back
25 #define pof pop_front
26 #define pob pop_back
27 #define ft first
28 #define sd second
29 #define mk make_pair
30 inline void SetIO(string Name) {
31     string Input = Name+".in",
32     Output = Name+".out";
33     freopen(Input.c_str(), "r", stdin),
34     freopen(Output.c_str(), "w", stdout);
35 }
36
37 const int N = 50010;
38 const DB Eps = 1e-5;
39 typedef pair<DB, DB> DD;
40 typedef pair<int, int> II;
41 map<II, int> MAP;
42 II L[N];
43 int n;
44 int Stack[N], Len;
45
46 inline void Input() {
47     scanf("%d", &n);
48     For(i, 1, n) scanf("%d%d", &L[i].ft, &L[i].sd);
49 }
50
51 inline DD Work(II L1, II L2) {
52     DB A1 = 1.0*L1.ft, B1 = 1.0*L1.sd,
53     A2 = 1.0*L2.ft, B2 = 1.0*L2.sd;
54     DD Ret;
55     Ret.ft = (B2-B1)/(A1-A2);
56     Ret.sd = A1*Ret.ft+B1;
57     return Ret;
58 }
59
60 inline void Solve() {
61     For(i, 1, n) MAP[L[i]] = i;
62     sort(L+1, L+1+n);
63     int _n = n;
64     n = 1;
65     For(i, 2, _n)
66         if(L[i].ft == L[n].ft) L[n] = L[i];
67         else L[++n] = L[i];
68
69     Stack[1] = 1, Len = 1;
70     For(i, 2, n) {
71         if(Len <= 1) Stack[++Len] = i;
72         else {
73             while(Len >= 2) {
74                 int x = Stack[Len], y = Stack[Len-1];
75                 DD P1 = Work(L[x], L[i]),
76                 P2 = Work(L[y], L[x]);
77                 if(P1.ft <= P2.ft+Eps) Len--;
78                 else break;
79             }
80             Stack[++Len] = i;
81         }
82     }
83
84     For(i, 1, Len) {
85         int x = Stack[i];
86         x = MAP[L[x]];
87         Stack[i] = x;
88     }
89     sort(Stack+1, Stack+1+Len);
90     For(i, 1, Len) cout<<Stack[i]<<‘ ‘;
91 }
92
93 int main() {
94     SetIO("1007");
95     Input();
96     Solve();
97     return 0;
98 }

思考:原本我是想判断1,3的交点是否在1,2的左侧,如果是则2被覆盖(因为已经按斜率排序了),

我感觉这个做法没问题,可是提交后WA了,请神牛告诉我为什么不对

时间: 2024-10-09 18:04:15

bzoj1007的相关文章

【BZOJ1007】[HNOI2008]水平可见直线 半平面交

[BZOJ1007][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

【BZOJ1007】水平可见直线(单调栈)

[BZOJ1007]水平可见直线(单调栈) 题解 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 < 50

[bzoj1007][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

[BZOJ1007] [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 从

【bzoj1007】[HNOI2008]水平可见直线 半平面交/单调栈

题目描述 在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条直线两两不重合.求出所有可见的直线. 输入 第一行为N(0 < N < 50000),接下来的N行输入Ai,Bi 输出 从小到大输出可见直线的编号,两两中间

【BZOJ1007】【HNOI2008】水平可见直线

链接: #include <stdio.h> int main() { puts("转载请注明出处[辗转山河弋流歌 by 空灰冰魂]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/46551367"); } 题解: 呃.把直线随便排下序,然后扫一遍,类似栈一样删掉被覆盖的直线. 代码: #include <cmath> #include <cstdio> #include

[BZOJ1007][HNOI2008]水平可见直线 计算几何

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1007 可以发现题目求的就是一个下凸包,把直线按斜率排序,再来维护凸包就好了.可以发现下凸包上的拐点横坐标单增.同时注意处理斜率相同的直线的情况. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const double eps=1e-14;

[BZOJ1007]水平可见直线

发现其实是一个下凸壳,所以先按斜率排序,然后判断当前直线与栈顶直线的交点是否更靠右 注意平行的情况 1 #include<bits/stdc++.h> 2 using namespace std; 3 4 #define maxn 50005 5 #define esp 1e-8 6 struct node{ 7 double a,b; 8 int id; 9 }V[maxn]; 10 double a[maxn],b[maxn]; 11 int sta[maxn],top; 12 bool

【bzoj1007】[HNOI2008]水平可见直线

先按斜率排序,再将最小的两条线入栈,然后依次处理每条线,如果其与栈顶元素的交点在上一个点的左边,则将栈顶元素出栈 : #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> using namespace std; #define eps 1e-8 #define N 5001

BZOJ1007|水平可见直线|模拟

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,BiOutput从小到大输出可见直