版权声明:若转载请附上原博客链接,谢谢! https://blog.csdn.net/Link_Ray/article/details/84545734
题意
如图所示,给一个n*m的黑白棋盘,列代表x,行代表y,分别给出两个矩形rec1,rec2的左下角和右上角坐标,rec1会把其覆盖的区域全部变成白色,rec2会把其覆盖的区域全部变成黑色。
rec1先,rec2后。
问最终棋盘有多少个白色格子和多少个黑色格子。
题解
①首先考虑初始给出n*m的棋盘中有多少个白格子和黑格子
- 对于面积是偶数的棋盘,黑白格子对半分
- 对于面积是奇数的棋盘,观察(1,1)格子颜色,如果是白色,则白色比黑色多1,否则黑色比白色多1。
②之后分开考虑一个矩形覆盖的情况
- 如果是白色矩形覆盖,那么可以用①的信息,计算出里面有多少个黑格子,就知道多了多少个白格子了。
- 左下角的坐标可以判断这个方块左下角是黑格子还是白格子,如果x+y是奇数则黑,反之白。
③考虑两个矩形重合
rec1: (x1,y1,x3,y3) rec2: (x2,y2,x4,y4)
- 重合矩形的左下角坐标为 max(x1,x3), max(y1,y3),右上角坐标为min(x2,x4), min(y2,y4)。
- 重合的情况便是,之前白色区域覆盖的黑色格子需要全部还回去,所以只需要算出重合区域初始有多少个黑格子即可 。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pll; // 1 黑 2白
const int maxn = 1e5+5;
pll fw(long long x, long long y) {
long long b = x*y/2;
long long w = x*y-b;
return pll(b,w);
}
pll fb(long long x, long long y) {
long long w = x*y/2;
long long b = x*y-w;
return pll(b,w);
}
int main() {
int T;
scanf("%d", &T);
while(T--) {
long long x,y; // m n
scanf("%lld%lld", &y, &x);
long long x1,x2,x3,x4,y1,y2,y3,y4;
scanf("%lld%lld%lld%lld", &x1,&y1, &x2, &y2); // 白
scanf("%lld%lld%lld%lld", &x3,&y3, &x4, &y4); // 黑
pll p = fw(x,y);
long long sb = p.first;
long long sw = p.second;
// cout <<"初始:" << sw <<" " << sb << endl;
long long c1 = x2-x1+1;
long long r1 = y2-y1+1;
long long c2 = x4-x3+1;
long long r2 = y4-y3+1;
long long dx = min(x2,x4)-max(x1,x3)+1;
long long dy = min(y2,y4)-max(y1,y3)+1;
long long _x3 = max(x1,x3);
long long _y3 = max(y1,y3);
if((x1+y1)%2 == 0) {
p = fw(c1,r1);
}
else {
p = fb(c1,r1);
}
sw += p.first; // 黑
sb -= p.first;
pll p2(0,0);
if((x3+y3)%2 == 0) {
p = fw(c2,r2);
}
else
p = fb(c2,r2);
sb += p.second; // 白
sw -= p.second;
if(dx > 0 && dy > 0) {
if((_x3+_y3)%2 == 0){
p2 = fw(dx,dy);
}
else
p2 = fb(dx,dy);
}
sw -= p2.first;
sb += p2.first;
cout << sw <<" " << sb << endl;
}
return 0;
}