1 条题解
-
0
自动搬运
来自洛谷,原作者为

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
- 上传者