【中山纪念中学六年级模拟赛】方格翻转 题解

题目大意

有无穷个格子,初始都是白色,现在有 \(n\) 个操作

每个操作讲左上角是格子 \(x_1,y_1\) ,右下角是格子 \(x_2,y_2\) 的矩形翻转,即白边黑,黑变白

最后问所有黑色格子组成图形的周长

题解

如果有两个矩形的边重合

2

1 1 4 4

2 3 5 4

重合的边消失


如果有三个矩形的边重合

3

1 1 4 4

2 3 5 4

3 4 3 4

可以发现重合奇数次的边还在,偶数次的消失


考虑计算一行的贡献

发现就是奇数点和它下一个点的距离

实现

  1. 把所有询问的矩形的 4 条边取出,放到数组里,要注意点转为边的差异
  2. 排序
  3. 分别同一行的点放在数组里,然后计算。
  4. 记得多算一行防止最后一行没算
#include<bits/stdc++.h>
using namespace std;
inline int Rd() {
	register int x=0;
	char C=getchar();
	for(;C<'0'||C>'9';C=getchar()) ;
	for(;C>'/'&&C<':';C=getchar()) x=(x<<1)+(x<<3)+(C^48);
	return x;
}
const int N=500005;
int n,p,q,o,ans,z[N];
struct pi {
	int l,st,ed;
}x[N],y[N];
inline bool cmp(pi a,pi b) {
	return a.l<b.l;
}
int main() {
	freopen("f.in","r",stdin);
	freopen("f.out","w",stdout);
	n=Rd();
	for(int i=1,a,b,c,d;i<=n;i++) {
		scanf("%d%d%d%d",&a,&b,&c,&d);
		x[++p]=(pi){a,b,d+1};
		x[++p]=(pi){c+1,b,d+1};
		y[++q]=(pi){b,a,c+1};
		y[++q]=(pi){d+1,a,c+1};
	}
	n=n<<1;
	sort(x+1,x+n+1,cmp);
	sort(y+1,y+n+1,cmp);
	
	for(int i=1;i<=n+1;i++) {
		if(x[i].l!=x[i-1].l) {
			sort(z+1,z+o+1);
			for(int j=1;j<o;j++)
				if(j&1)ans+=z[j+1]-z[j];
			o=0;
		}
		z[++o]=x[i].st;
		z[++o]=x[i].ed;
	}
	o=0;
	for(int i=1;i<=n+1;i++) {
		if(y[i].l!=y[i-1].l) {
			sort(z+1,z+o+1);
			for(int j=1;j<o;j++)
				if(j&1)ans+=z[j+1]-z[j];
			o=0;
		}
		z[++o]=y[i].st;
		z[++o]=y[i].ed;
	}
	printf("%d",ans);
} 

Thanks

hybb 提供图/做法

原文地址:https://www.cnblogs.com/KonjakLAF/p/14583968.html