P3194 [HNOI2008] 水平可见直线

原题链接

题解

想象一下,从左上角无限大的地方开始,第一个看到的一定是斜率最小的且截距最大的,慢慢往右下角滑,第一个碰到的直线一定是斜率比前一个小(不一定是第二小)的但是是它的斜率所属直线里截距最大的
重复上述步骤,最外面的直线一定长这样

图片来自luogu,linaonao

所以我们可以按斜率排序所有直线,斜率相同的直线按截距排序
如果出现一条直线斜率大但是截距也大,那么它可能会盖过前边斜率小的直线,所以有点像单调栈,因为它会一直盖直到盖不住,这样那些被盖住的直线就被弹出去了

感觉讲的还不是很清晰,水平还不够

code

#include<bits/stdc++.h>
using namespace std;
struct node
{
    double a,b;
    int id;
}line[500005];

int q[500005];

bool cmp(node x,node y)
{
    if(x.a!=y.a) return x.a<y.a;
    return x.b>y.b;
}

bool cmp2(int i,int j)
{
    return line[i].id<line[j].id;
}

double cal(int i,int j)
{
    node x=line[i],y=line[j];
    return 1.0*(y.b-x.b)/(x.a-y.a);
}

int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>line[i].a>>line[i].b;
        line[i].id=i;
    }

    sort(line+1,line+1+n,cmp);


    q[1]=1;
    int top=1;
    for(int i=2;i<=n;i++)
    {
        if(line[i].a==line[q[top]].a) continue;
        while(top>1&&cal(i,q[top-1])<=cal(q[top],q[top-1]))top--;
        q[++top]=i;
    }

    sort(q+1,q+1+top,cmp2);

    for(int i=1;i<=top;i++) cout<<line[q[i]].id<<" ";
    return 0;
}

posted @   纯粹的  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示