F - City Park Gym - 100783F计算几何+并查集

xiaoxiao2021-02-28  134

题意:

给出许多个矩形,不重叠

问连通的矩阵块面积最大是多少

题解:

因为没有重叠的,所以我们可以分别对水平线和垂直线进行并查集合并

这里我犯了一个并查集的错误,就是在累加面积的时候写反了

void Unite(int num1,int num2) { int tx=find_it(num1); int ty=find_it(num2); if(tx!=ty){ father[tx]=ty; sum[ty]+=sum[tx]; } }上面写成了sum【tx】+=sum【ty】了导致错误

这里还需注意的是,处理同一水平线上的线段要注意大小关系

两份代码,供参考

#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define MAXN 100050 #define LL long long int father[MAXN]; LL sum[MAXN]; struct Point { int x,y; }; struct Line { Point p1,p2; int pos; }a[MAXN<<1],b[MAXN<<1]; int cmp1(Line A,Line B) { if(A.p1.y==B.p1.y) return A.p1.x < B.p1.x; return A.p1.y < B.p1.y; } int cmp2(Line A,Line B) { if(A.p1.x==B.p1.x) return A.p1.y < B.p1.y; return A.p1.x < B.p1.x; } int find_it(int x) { int tempx=x,t; while(tempx!=father[tempx]) tempx=father[tempx]; while(x!=father[x]) { t=father[x]; father[x]=tempx; x=t; } return tempx; } void Unite(int num1,int num2) { int tx=find_it(num1); int ty=find_it(num2); if(tx!=ty){ father[tx]=ty; sum[ty]+=sum[tx]; } } int main() { int n; //freopen("in.txt","r",stdin); while(scanf("%d",&n)!=EOF) { int x,y,w,h; memset(sum,0,sizeof(sum)); for(int i=0;i<n;i++){ scanf("%d%d%d%d",&x,&y,&w,&h); ///水平线段 a[i*2].p1.x=x , a[i*2].p1.y=y; a[i*2].p2.x=x+w, a[i*2].p2.y=y; a[i*2].pos=i; a[i*2+1].p1.x=x , a[i*2+1].p1.y=y+h; a[i*2+1].p2.x=x+w, a[i*2+1].p2.y=y+h; a[i*2+1].pos=i; ///垂直线段 b[i*2].p1.x=x , b[i*2].p1.y=y; b[i*2].pos=i; b[i*2].p2.x=x , b[i*2].p2.y=y+h; b[i*2+1].p1.x=x+w, b[i*2+1].p1.y=y; b[i*2+1].pos=i; b[i*2+1].p2.x=x+w, b[i*2+1].p2.y=y+h; sum[i]=w*h; } for(int i=0;i<=n;i++) father[i]=i; sort(a,a+n*2,cmp1); sort(b,b+n*2,cmp2); int last_x=a[0].p2.x,ty=a[0].p2.y; int last_y=b[0].p2.y,tx=b[0].p2.x; for(int i=1;i<n*2;i++){ if(a[i].p1.y==a[i-1].p1.y){ if(a[i].p1.y!=ty){ last_x=a[i-1].p2.x; ty=a[i].p1.y; } if(last_x>=a[i].p1.x) Unite(a[i-1].pos,a[i].pos); last_x=last_x>a[i].p2.x?last_x:a[i].p2.x; } if(b[i].p1.x==b[i-1].p1.x){ if(tx!=b[i].p1.x){ tx=b[i].p1.x; last_y=b[i-1].p2.y; } if(last_y>=b[i].p1.y) Unite(b[i-1].pos,b[i].pos); last_y=last_y>b[i].p2.y?last_y:b[i].p2.y; } } LL ans=0; for(int i=0;i<n;i++) ans=ans>sum[i]?ans:sum[i]; printf("%lld\n",ans); } return 0; }

#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define MAXN 100050 #define LL long long int father[MAXN]; int sum[MAXN]; int W[MAXN],H[MAXN]; struct Line { int x,l,r,id; Line(int x=0,int l=0,int r=0,int id=0):x(x),l(l),r(r),id(id){} bool operator < (const Line &b)const{ return x<b.x||(x==b.x&&l<b.l)||(x==b.x&&l==b.l&&r<b.r); } }; Line a[MAXN*3],b[MAXN*3]; int find_it(int x) { if(father[x]!=x) father[x]=find_it(father[x]); return father[x]; } int main() { int n; //freopen("in.txt","r",stdin); while(scanf("%d",&n)!=EOF) { int x,y,w,h; memset(sum,0,sizeof(sum)); for(int i=0;i<n;i++){ scanf("%d%d%d%d",&x,&y,&w,&h); ///水平线段 a[i]=Line(y,x,x+w,i); a[i+n]=Line(y+h,x,x+w,i); ///垂直线段 b[i]=Line(x,y,y+h,i); b[i+n]=Line(x+w,y,y+h,i); W[i]=w; H[i]=h; father[i]=i; } int m=n<<1; sort(a,a+m); sort(b,b+m); for(int i=0;i<m;){ int j=i,mx=a[i].r; while(j<=m&&a[j].x==a[i].x) { if(a[j].l<=mx){ int tx=find_it(a[j].id); int ty=find_it(a[i].id); if(tx!=ty) father[tx]=ty; mx=max(mx,a[j].r); j++; } else break; } i=j; } for(int i=0;i<m;){ int j=i,mx=b[i].r; while(j<=m&&b[j].x==b[i].x) { if(b[j].l<=mx){ int tx=find_it(b[j].id); int ty=find_it(b[i].id); if(tx!=ty) father[tx]=ty; mx=max(mx,b[j].r); j++; } else break; } i=j; } int ans=0; int t; for(int i=0;i<n;i++){ t=find_it(i); sum[t]+=W[i]*H[i]; ans=max(ans,sum[t]); } printf("%d\n",ans); } return 0; }

转载请注明原文地址: https://www.6miu.com/read-30225.html

最新回复(0)