题目大意
有无穷个格子,初始都是白色,现在有 \(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
可以发现重合奇数次的边还在,偶数次的消失
考虑计算一行的贡献
发现就是奇数点和它下一个点的距离
实现
- 把所有询问的矩形的 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 提供图/做法