全WA代码:
//当时想的时候只是想到了两个矩形的重叠、覆盖有无交点的问题 //当时还庆幸自己写的一定不会越界(毕竟考虑了负数的问题) //以后一定要对拍~~ //却 没考虑三个及以上的重叠、交叉、大的完全包含小的,多个交点如何选取等问题 #include<cstdio> #include<algorithm> using namespace std; #define N 101000 struct node{ int x1,y1,x2,y2; }q[N]; int p,n,h[N],l[N],r[N]; struct ss{ int x,y; }ans[N]; bool next=0; inline bool cmp(const node &x,const node &y){ return x.x1<y.x1; } inline int read(){ register int x=0,f=1; register char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return x*f; } int main(){ n=read(); for(int i=1;i<=n;i++) h[i]=read(),l[i]=read(),r[i]=read(); for(int i=1;i<=n;i++) q[i].x1=l[i],q[i].x2=r[i],q[i].y1=h[i],q[i].y2=0; stable_sort(q+1,q+n+1,cmp); ans[++p]=(ss){q[1].x1,q[1].y2};ans[++p]=(ss){q[1].x1,q[1].y1}; for(int i=1;i<n;i++){ if(next){ ans[++p]=(ss){q[i].x1,q[i].y2};ans[++p]=(ss){q[i].x1,q[i].y1}; next=0; } if(q[i+1].x1<=q[i].x2){ if(q[i+1].y1>q[i].y1){ if(q[i+1].y1==ans[p].y) ans[++p]=(ss){q[i+1].x1,q[i+1].y1},ans[++p]=(ss){q[i+1].x1,q[i].y1}; else ans[++p]=(ss){q[i+1].x1,q[i].y1},ans[++p]=(ss){q[i+1].x1,q[i+1].y1}; continue; } if(q[i+1].y1<q[i].y1){ if(q[i].y1==ans[p].y) ans[++p]=(ss){q[i].x2,q[i].y1},ans[++p]=(ss){q[i].x2,q[i+1].y1}; else ans[++p]=(ss){q[i].x2,q[i+1].y1},ans[++p]=(ss){q[i].x2,q[i].y1}; } } else ans[++p]=(ss){q[i].x2,q[i].y1},ans[++p]=(ss){q[i].x2,q[i].y2},next=1; } ans[++p]=(ss){q[n].x2,q[n].y1};ans[++p]=(ss){q[n].x2,q[n].y2}; printf("%d ",p); for(int i=1;i<=p;i++) printf("%d %d ",ans[i].x,ans[i].y); return 0; }
附上第一个点的数据,希望对你有帮助
输入数据 (显示前20行)
10 728585422 -975253598 -151882490 374575876 -254784146 181181594 833835437 47288945 148848803 759458501 -436030326 231976018 728539762 -955496022 185702254 638227308 217298309 704986111 510564969 -494836052 761895956 615469816 -832995214 535449271 272606304 -614433803 -467384146 557024592 287991704 679834400
正确答案
14 -975253598 0 -975253598 728585422 -436030326 728585422 -436030326 759458501 47288945 759458501 47288945 833835437 148848803 833835437 148848803 759458501 231976018 759458501 231976018 638227308 704986111 638227308 704986111 510564969 761895956 510564969 761895956 0
自己离散化画一下图,可能就知道为什么了。
这是做的第一个扫描线的题目,详细整理一下,留作纪念。
正解:
扫描线+堆排序(显然不是题解的代码,没那么无聊抄代码玩)
AC代码:
#include<cstdio> #include<queue> #include<algorithm> using namespace std; #define N 100100 struct ss{ int h,l,r; bool operator < (const ss &a) const{ if(l==a.l) return h>a.h;//双关键字排序 return l<a.l; } }e[N<<1]; struct node{ int h,r; node(ss x){h=x.h,r=x.r;} bool operator < (const node &a) const{ return h<a.h; } }; int n,cnt;//记录点的个数 pair<int,int>ans[N<<2];//记录答案点的坐标 priority_queue<node>que;//大根堆 ss bfs(ss now,int x){//更新now,处理记录扫描后的矩形的右端点 while(!que.empty()){ node nown=que.top();que.pop(); if(nown.r>now.r){//有比它宽的,且比它矮的 if(nown.h!=now.h) ans[++cnt]=make_pair(now.r,now.h),ans[++cnt]=make_pair(now.r,nown.h); now.r=nown.r;now.h=nown.h; } if(now.r>=x) return now;//* } //队列空说明:有断层 ans[++cnt]=make_pair(now.r,now.h),ans[++cnt]=make_pair(now.r,0);//断层左边的两个点 now.h=0;now.r=0x7fffffff;//now.h清零,now.r=inf为的是覆盖全区间,在*处起作用 return now; } void solve(){ ans[++cnt]=make_pair(e[1].l,0);ans[++cnt]=make_pair(e[1].l,e[1].h);//记录左边界答案 ss now=e[1]; for(int i=2;i<=n;i++){//总共分 ①②③ 三大情况,前两种比较直观,第三种比较难处理 if(now.h>=e[i].h&&now.r>=e[i].l) que.push(e[i]);//① 存入堆,做备用最高点(这里处理了包含的情况) if(now.h<e[i].h&&now.r>=e[i].l){//② que.push(now);//把比当前最高点低的点都存入堆,一个也不能漏 ans[++cnt]=make_pair(e[i].l,now.h);//较低点 now=e[i]; ans[++cnt]=make_pair(e[i].l,now.h);//较高点 } if(now.r<e[i].l){//③ now=bfs(now,e[i].l);//判断一个矩形横穿e[i]这个矩形 if(now.h>=e[i].h&&now.r>=e[i].l) que.push(e[i]); if(now.h<e[i].h&&now.r>=e[i].l){//断层和比他低的一起处理 que.push(now);//上边的now=bfs..和这里很好的处理了输出点坐标的顺序问题 ans[++cnt]=make_pair(e[i].l,now.h); now=e[i]; ans[++cnt]=make_pair(e[i].l,now.h); } } } bfs(now,0x7fffffff);//遍历全区间做收尾工作:因为最后一个点的右边界不一定是所有元素的最右边界 //总结:只要最高点发生跃迁,就要记录答案 } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d%d%d",&e[i].h,&e[i].l,&e[i].r); sort(e+1,e+n+1);//左端点升序排列 solve(); printf("%d ",cnt); for(int i=1;i<=cnt;i++) printf("%d %d ",ans[i].first,ans[i].second);//因为记录是按顺序记录的,所以按顺序输出即可 return 0; }