BZOJ 1007: [HNOI2008]水平可见直线 几何

按斜率排序,斜率线相同的直线取截距最大的

一条直线能够被看到的条件是,与比它斜率小的交点在比它斜率大的交点的左侧

1007: [HNOI2008]水平可见直线

Time Limit: 1 Sec  Memory Limit: 162 MB

Submit: 4234  Solved: 1558

[Submit][Status][Discuss]

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

C++:

/* ***********************************************
Author        :CKboss
Created Time  :2015年05月10日 星期日 08时38分36秒
File Name     :BZOJ1007.cpp
************************************************ */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <set>
#include <map>

using namespace std;

const int maxn=50500;

int n;
struct Line
{
	int id;
	int k,b;
}line[maxn];

bool cmp(Line A,Line B)
{
	if(A.k!=B.k) return A.k<B.k;
	return A.b>B.b;
}

Line stack[maxn];
int st;

double cal(Line X,Line Y) /// Line X < Line Y
{
	return (double)(Y.b-X.b)/(X.k-Y.k);
}

int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);

	scanf("%d",&n);
	for(int i=0;i<n;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		line[i]=(Line){i+1,x,y};
	}
	sort(line,line+n,cmp);
	int m=0;
	int lastk=8888888;
	for(int i=0;i<n;i++)
	{
		if(lastk!=line[i].k)
		{
			line[m++]=line[i];
			lastk=line[i].k;
		}
	}
	n=m;
	stack[st++]=line[0];

	for(int i=1;i<n;i++)
	{
		while(st>1&&cal(stack[st-2],stack[st-1])>=cal(stack[st-1],line[i]))
			st--;
		stack[st++]=line[i];
	}

	vector<int> v;
	for(int i=0;i<st;i++) v.push_back(stack[i].id);
	sort(v.begin(),v.end());
	for(int i=0;i<st;i++)
		printf("%d ",v[i]);
	putchar(10);

    return 0;
}

JAVA:

import java.util.*;

public class Main {

	final int maxn=50500;
	final double eps = 1e-7;

	int n;

	public class Line{
		public int k,b,id;
	}

	public class cmp1 implements Comparator{
		public int compare(Object x,Object y){
			Line A=(Line)x,B=(Line)y;
			if(A.k!=B.k) return A.k-B.k;
			return B.b-A.b;
		}
	}

	Line[] line=new Line[maxn];

	double CAL(Line A,Line B){
		return (double)(B.b-A.b)/(A.k-B.k);
	}

	Line[] Stack=new Line[maxn];
	int st;

    public Main() {

    	Scanner in = new Scanner(System.in);
    	n=in.nextInt();
    	for(int i=0;i<n;i++){
			line[i]=new Line();
    		line[i].k=in.nextInt();
    		line[i].b=in.nextInt();
			line[i].id=i+1;
    	}
    	Arrays.sort(line,0,n,new cmp1());
		int last=888888;
		int m=0;
    	for(int i=0;i<n;i++){
			if(line[i].k!=last){
				line[m++]=line[i];
				last=line[i].k;
			}
    	}
		n=m;
		Stack[0]=line[0]; st=1;
		for(int i=1;i<n;i++){
			while(st>1&&CAL(Stack[st-1],Stack[st-2])>=CAL(Stack[st-1],line[i]))
				st--;
			Stack[st++]=line[i];
		}

		Vector vi=new Vector<Integer>();
		for(int i=0;i<st;i++){
			vi.add(Stack[i].id);
		}
		Collections.sort(vi);
		for(int i=0;i<st;i++){
			System.out.printf("%d ",vi.get(i));
		}
    }

    public static void main(String[] args){
    	new Main();
    }
}
时间: 2024-10-09 21:51:53

BZOJ 1007: [HNOI2008]水平可见直线 几何的相关文章

BZOJ 1007: [HNOI2008]水平可见直线( 计算几何 )

按A从小到大排序然后用栈解决. -------------------------------------------------------------------- #include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 50009; struct L { int A, B, id; inline void Read(int p) { scanf("%d%d"

bzoj 1007 [HNOI2008]水平可见直线(单调栈)

1007: [HNOI2008]水平可见直线 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 5120  Solved: 1899[Submit][Status][Discuss] Description 在xoy直角坐标平面上有n条直线L1,L2,...Ln,若在y值为正无穷大处往下看,能见到Li的某个子线段,则称Li为可见的,否则Li为被覆盖的.     例如,对于直线:     L1:y=x; L2:y=-x; L3:y=0     则L1和L

BZOJ 1007: [HNOI2008]水平可见直线 栈/计算几何

1007: [HNOI2008]水平可见直线 Time Limit: 1 Sec  Memory Limit: 162 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id=1007 Description 在xoy直角坐标平面上有n条直线L1,L2,...Ln,若在y值为正无穷大处往下看,能见到Li的某个子线段,则称Li为可见的,否则Li为被覆盖的.     例如,对于直线:     L1:y=x; L2:y=-x; L3:y=0  

bzoj 1007: [HNOI2008]水平可见直线(计算几何)

1007: [HNOI2008]水平可见直线 Time Limit: 1 Sec  Memory Limit: 162 MB Submit: 5503  Solved: 2078 [Submit][Status][Discuss] Description 在xoy直角坐标平面上有n条直线L1,L2,...Ln,若在y值为正无穷大处往下看,能见到Li的某个子线段,则称Li为 可见的,否则Li为被覆盖的. 例如,对于直线: L1:y=x; L2:y=-x; L3:y=0 则L1和L2是可见的,L3是

BZOJ 1007 HNOI2008 水平可见直线 半平面交

题目大意:给定n条直线,求从上到下俯瞰能看到哪些直线 半平面交的裸题 首先将所有直线按照斜率排序,依次入栈 如果一条直线和栈顶的交点在栈顶直线和栈顶下面那条直线的交点的左侧,则删除栈顶 若多条直线斜率相同,只插入截距最大的那条直线 最后记录答案输出即可 #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define

bzoj 1007: [HNOI2008]水平可见直线

1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #define M 1000000 5 using namespace std; 6 struct data 7 { 8 int k,b,nu; 9 }a[M]; 10 int n,q[M],t; 11 bool cmp(data a1,data a2) 12 { 13 if(a1.k==a2.k) 14 return a1.b<a2.b

bzoj 1007: [HNOI2008]水平可见直线【半平面交】

其实并不算标准半平面交?但是思路差不多 先按照斜率排序,然后用栈维护凸壳,每遇到重斜率或a[i],s[top-1]交点的x轴在s[top],s[top-1]交点左侧,则说明s[top]被a[i],s[top-1]覆盖,弹栈即可: #include<iostream> #include<cstdio> #include<algorithm> using namespace std; const int N=50005; const double eps=1e-8; int

1007: [HNOI2008]水平可见直线[维护下凸壳]

1007: [HNOI2008]水平可见直线 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 7184  Solved: 2741[Submit][Status][Discuss] Description 在xoy直角坐标平面上有n条直线L1,L2,...Ln,若在y值为正无穷大处往下看,能见到Li的某个子线段,则称Li为可见的,否则Li为被覆盖的.例如,对于直线:L1:y=x; L2:y=-x; L3:y=0则L1和L2是可见的,L3是被覆盖的.给

【凸壳】【HNOI 2008】【bzoj 1007】水平可见直线

1007: [HNOI2008]水平可见直线 Time Limit: 1 Sec Memory Limit: 162 MB Submit: 4567 Solved: 1686 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|,|