题意:
给一个n*m块大的黑白相间的矩形,在这个举行中操作,要先把第一个矩形(左下角坐标(x1,y2),右上角坐标(x2,y2)) 全部涂成白色,再把第二个矩形(左下角坐标(x3,y3),右上角坐标(x4,y4)) 全部涂成黑色。 求涂了这两个矩形之后的 白色块数量和黑色块数量。
思路:
上图。因为在第二步中全涂成黑色,可能会 覆盖第一个矩形的一部分。如果先求白色块,然后通过n*m-白色再求出黑色的方法,不太好求。所以先求黑色块数量,再通过n*m-黑色 求白色。
答案黑色块的数量设为numblack ( 即nb ),nb = n*m中总的黑色数量 - s1中的黑色数量 - s2中的黑色数量 - s3中的黑色数量 + (s2+s3)的面积, 等价于nb = n*m中总的黑色数量 - (s1+s2)中的黑色数量 - (s2+s3)中的黑色数量 + s2中的黑色数量 + (s2+s3)的面积。这样比较好求。
而求一个矩形中黑色方块的数量,容易知道不是 白==黑 ,就是 白与黑相差为1(其中矩形左下角是黑色的话,黑色的数量就会比白色多1,这也是必要条件)
xx1=max(x[1],x[3]);
xx2=min(x[2],x[4]);
yy1=max(y[1],y[3]);
yy2=min(y[2],y[4]); 如果 xx1<=xx2 && yy1<=yy2 ,则有重叠面积,s2部分存在。


1 #include<iostream> 2 #include<cstdio> 3 #include <cctype> 4 #include<algorithm> 5 #include<cstring> 6 #include<cmath> 7 #include<string> 8 #include<cmath> 9 #include<set> 10 #include<vector> 11 #include<stack> 12 #include<queue> 13 #include<map> 14 using namespace std; 15 #define ll long long 16 #define mem(a,x) memset(a,x,sizeof(a)) 17 #define se second 18 #define fi first 19 const ll mod=1000000007; 20 const int INF= 0x3f3f3f3f; 21 const int inf= 1000002; 22 const int N=1e5+5; 23 24 int t,n,m; 25 ll x[5],y[5]; 26 ll nb; 27 28 ll numblack(ll x1,ll y1,ll x2,ll y2) 29 { 30 // 矩形里 黑色数量要+1的唯一情况: 31 if((x2-x1+1)%2==1 && (y2-y1+1)%2==1 && (x1+y1)%2==1) 32 return (x2-x1+1)*(y2-y1+1)/2 +1; 33 else 34 return (x2-x1+1)*(y2-y1+1)/2 ; 35 } 36 37 int main() 38 { 39 cin>>t; 40 while(t--) 41 { 42 scanf("%d%d",&n,&m); 43 for(int i=1;i<=4;i++) 44 scanf("%d%d",&x[i],&y[i]); 45 46 nb = numblack(1,1,m,n); 47 nb-= numblack( x[1],y[1],x[2],y[2] ); 48 nb-= numblack( x[3],y[3],x[4],y[4] ); 49 50 ll xx1=max(x[1],x[3]); 51 ll xx2=min(x[2],x[4]); 52 ll yy1=max(y[1],y[3]); 53 ll yy2=min(y[2],y[4]); 54 if(xx1<=xx2 && yy1<=yy2) //如果重叠 加上重合部分(容斥定理) 55 nb+= numblack( xx1,yy1,xx2,yy2 ); 56 57 nb+= (x[4]-x[3]+1)*(y[4]-y[3]+1); 58 cout<<1LL*n*m-nb<<' '<<nb<<endl; 59 } 60 }