1 条题解

  • 0
    @ 2025-8-24 21:24:28

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar shuri001
    **

    搬运于2025-08-24 21:24:27,当前版本为作者最后更新于2017-10-22 20:56:37,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    扫描线

    注释非常详细 请看看ovo

    #include<cstdio>
    #include<set>
    #include<algorithm>
    using namespace std;
    int n,cnt,num;
    struct build{
        int h,l,r;//高,左,右 
    }a[100010];
    struct line{
        int up,x,k;//高,x轴,出入属性 
    }l[200020];//扫描线 
    struct ANS{
        int ax,ay;//左边,右边 
    }ans[400040];
    int read(){
        char c=getchar();int num=0,flag=1;
        while(c<'0'||c>'9'){if(c=='-')flag=-1;c=getchar();}
        while(c>='0'&&c<='9'){num=num*10+c-'0';c=getchar();}
        return num*flag;
    

    }//读入优化

    multiset<int>s;//存高度,默认递增,可以重复 
    int cmp(line i,line j){
        if(i.x!=j.x)return i.x<j.x;//如果靠左的排到前面 
        if(i.k!=j.k)return i.k<j.k;//入边在前 
        if(i.k==1)return i.up>j.up;//入边越高越容易挡住 
        if(i.k==2)return i.up<j.up;//出边越矮越容易挡住 
    }
    int main(){
        n=read();//读边数 
        for(int i=1;i<=n;i++){
            a[i].h=read(),a[i].l=read(),a[i].r=read();//读入 
            l[++cnt].up=a[i].h,l[cnt].x=a[i].l,l[cnt].k=1;//加入边 
            l[++cnt].up=a[i].h,l[cnt].x=a[i].r,l[cnt].k=2;//加出边 
        }
        sort(l+1,l+cnt+1,cmp);//为扫描排序 
        s.insert(0);//初始最大高度为0 
        for(int i=1;i<=cnt;i++){
            int mx=*s.rbegin();//取最高的高度 
            if(l[i].k==1){//如果是入边 
                if(l[i].up<=mx) s.insert(l[i].up);//比最高矮,加入堆 
                else{
                    ++num;ans[num].ax=l[i].x;ans[num].ay=mx;//记录交叉点 
                    ++num;ans[num].ax=l[i].x;ans[num].ay=l[i].up;//记录交叉点上面的点 
                    s.insert(l[i].up);//加高 
                }
            }
            if(l[i].k==2){//如果是出边 
                if(l[i].up==mx&&s.count(mx)==1){//如果当前的就是最高的线,而且,没有跟它一样高的 
                    s.erase(mx);//取出这一条 
                    ans[++num].ax=l[i].x; ans[num].ay=l[i].up;// 记录右上顶点 
                    ans[++num].ax=l[i].x;ans[num].ay=*s.rbegin();//记录交叉点 
                }
                else s.erase(s.find(l[i].up));//删掉一样高的边 
            }
        }
        printf("%d\n",num);//输出节点个数 
        for(int i=1;i<=num;i++)   printf("%d %d\n",ans[i].ax,ans[i].ay); //输出结果 
        return 0;
    }
    
    
    • 1

    信息

    ID
    379
    时间
    1000ms
    内存
    125MiB
    难度
    5
    标签
    递交数
    0
    已通过
    0
    上传者