1、思路:
最终结果计算所有的白色块的个数,黑色块的个数。
可以只计算白色块的个数,黑色块的个数 = m*n-白色块的个数
题中白色块的数量ans = 第一次被白色覆盖掉的黑色的数量n1 + 第二次被黑色覆盖掉的白色数量n2.
由于两个区间有重合的部分,所以要对重合的部分进行计算。
我们每次刷漆时只考虑纯色覆盖到网格上的情况。
所以,
ans = 给未处理的棋盘刷白漆所覆盖掉的黑色格子的数量nn1 + 给未处理的棋盘刷黑漆所覆盖掉的白色格子的数量nn2 - 给重合
区域刷白漆所覆盖掉的黑色格子的数量nn3。
因为在第二次给棋盘刷漆时,如果不考虑之前白漆的作用,只去掉了棋盘上原本白色的格子,
但是在第一次刷白漆覆盖掉的黑色格子的数量nn3却没有考虑,所以+nn3,就可以了。
给出一个矩形两角顶点的坐标,可以求出这个矩形中的黑色格子的数量和白色格子的数量。
从矩形的左下角开始算起,左下角的颜色的数量一定是n*m/2(当n*m为偶数时),或者n*m/2+1(当n*m为奇数时)。
感谢阿力的点拨(*^▽^*)。
2、代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
LL f(LL x1,LL y1,LL x2,LL y2,LL fg){
LL n = x2-x1+1,m = y2-y1+1;
if((x1+y1)%2==fg){
if(n*m%2==0) return n*m/2;
else return n*m/2+1LL;
}
return n*m/2;
}
int main(void){
int T;
scanf("%d",&T);
while(T--){
LL n,m;
LL x1,y1,x2,y2;
LL a1,b1,a2,b2;
scanf("%lld%lld",&n,&m);
scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2);
scanf("%lld%lld%lld%lld",&a1,&b1,&a2,&b2);
LL xx1 = max(x1,a1);
LL yy1 = max(y1,b1);
LL xx2 = min(x2,a2);
LL yy2 = min(y2,b2);
LL W = f(1,1,n,m,0);
W += f(x1,y1,x2,y2,1);
W -= f(a1,b1,a2,b2,0);
//printf("%lld %lld %lld>>>>%lld>\n",f(1,1,n,m,0),f(x1,y1,x2,y2,1),f(a1,b1,a2,b2,0),W);
if(xx2>=xx1&&yy2>=yy1){
W -= f(xx1,yy1,xx2,yy2,1);
}
LL B = n*m-W;
printf("%lld %lld\n",W,B);
}
return 0;
}