zoukankan      html  css  js  c++  java
  • 【BZOJ1007】【HNOI2008】水平可见直线

    Description

      
    ​  传送门
      
      
      
         
      

    Solution

      
    ​  感觉有点套路,反正我想不到。
      
      首先对于斜率相同的直线,显然除了截距最大的一条,其他都是不可见的,直接删去。
      
      观察答案的上表面,它其实是一个由所有可见直线围成的下凸包。
      
      如果将剩余直线按斜率递增作为第一关键字、截距递减按第二关键字排序,并逐个加入,维护下凸包。
      
      类似普通下凸包,我们开一个栈(s)表示当前凸包由哪一些直线组成。
      
      新加入一条直线时,首先它在当前局面一定会作为凸包的一部分。但是它的加入导致哪一些直线被覆盖了呢?考虑栈尾直线是否被覆盖,它被覆盖的情况如下:
      

      
      即当新直线与(S_{t-1})的交点的(x)坐标小于等于(S_{t-1})(S_{t})交点的(x)坐标时,(S_t)会被覆盖。所以我们不断将被覆盖的直线从队尾弹出,最后加入新直线。
      
      
      
      
      

    Code

      

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    const int N=50005;
    int n;
    struct Line{int k,b,id;}a[N];
    int sta[N],top;
    bool cmp(const Line &u,const Line &v){
    	if(u.k!=v.k) return u.k<v.k;
    	return u.b>v.b;
    }
    bool cmp2(const int &u,const int &v){return a[u].id<a[v].id;}
    double inter(int i,int j){
    	return 1.0*(a[j].b-a[i].b)/(a[i].k-a[j].k);	
    }
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++) scanf("%d%d",&a[i].k,&a[i].b),a[i].id=i;
    	sort(a+1,a+1+n,cmp);
    	int tn=n;
    	n=0;
    	for(int i=1,j;i<=tn;){
    		j=i;	
    		a[++n]=a[i];
    		for(i++;i<=tn&&a[i].k==a[j].k;i++);
    	}
    	for(int i=1;i<=n;i++){
    		while(top>1&&inter(sta[top-1],i)<=inter(sta[top-1],sta[top]))
    			top--;
    		sta[++top]=i;							
    	}
    	sort(sta+1,sta+1+top,cmp2);
    	for(int i=1;i<=top;i++) printf("%d ",a[sta[i]].id);
    	return 0;
    }
    
  • 相关阅读:
    Linux系统下搭建Gitlab服务器
    Sqlserver数据库表转换成C#实体类
    C# 获取今天,昨天,上周,下周,上月,下月等等一些日期格式【转】
    Funthing
    网页生成海报
    NET 5.0 Swagger API 自动生成MarkDown文档
    说说C# 8.0 新增功能Index和Range的^0是什么?
    tblive-studio vs2019 编译过程记录
    确定已安装的 .NET Framework 版本
    修改CMD默认编码
  • 原文地址:https://www.cnblogs.com/RogerDTZ/p/9255812.html
Copyright © 2011-2022 走看看