[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
-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; }