题目大意:给你一个n*m的图形有白块和黑块,第一次操作将x1,y1,x2,y2矩形中所有块变为白块,第二次操作将x3,y3,x4,y4所有块变为黑块,最后问白块和黑块的总数。
思路:先分别把每次操作的影响加到总数中。要注意一点的是当方块面积为偶数时,白块黑块,各占一半,面积为奇数时,左下角的块会多一个,(x+y)是偶数则是白块,反则为黑块。
然后判断两个方块有没有交集,这里用到类似容斥的思想,减掉交集中白块多算的,加上黑块少算的,白块多算的即为交集中黑色的块,因为第一次操作将黑的变为白的是多余的,
这里通过
tx1=max(x[1],x[3]);
ty1=max(y[1],y[3]);
tx2=min(x[2],x[4]);
ty2=min(y[2],y[4]);
if(tx1<=tx2&&ty1<=ty2)成立时即为交集,这里可以画一个图理解一下,
查看题解的时候发现有人用矩形切割做的,然后就去学习了一下矩形切割,这道题也可以用这个思想。
矩形切割
#include<bits/stdc++.h>
#define fi first
#define se second
#define FOR(a) for(int i=0;i<a;i++)
#define sc(a) scanf("%d",&a)
#define show(a) cout<<a<<endl;
#define show2(a,b) cout<<a<<" "<<b<<endl;
#define show3(a,b,c) cout<<a<<" "<<b<<" "<<c<<endl;
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
typedef pair<P, int> LP;
const ll inf = 1e17 + 10;
const int N = 1e6 + 10;
const ll mod = 1e9+7;
map<string, int>ml;
ll c[N], vis[N], num[N], t, n, m, x, y, k, a[N],sum;
ll cx[100],cy[100];
ll ex, ey, cnt, ans;
ll dist[N];
ll dp[N];
multiset<ll> se;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>t;
while(t--)
{
cin>>x>>y;
ll sx,sy;
sx=x*y/2;
sy=x*y/2;
if((x*y)&1)
{
sx=x*y/2+1;
}
//cout<<sx<<" "<<sy<<endl;
for(int i=1;i<=4;i++)
{
cin>>cx[i]>>cy[i];
}
ll dis1=cx[2]-cx[1]+1;
ll dis2=cy[2]-cy[1]+1;
sx+=dis1*dis2/2;
sy-=dis1*dis2/2;
if(((dis1*dis2)&1)&&(cx[1]+cy[1])&1)sx+=1,sy-=1;
//cout<<sx<<" "<<sy<<endl;
dis1=cx[4]-cx[3]+1;
dis2=cy[4]-cy[3]+1;
sx-=dis1*dis2/2;
sy+=dis1*dis2/2;
if(((dis1*dis2)&1)&&(cx[3]+cy[3])%2==0)sx-=1,sy+=1;
//cout<<sx<<" "<<sy<<endl;
ll tx1=max(cx[1],cx[3]);
ll ty1=max(cy[1],cy[3]);
ll tx2=min(cx[2],cx[4]);
ll ty2=min(cy[2],cy[4]);
//cout<<tx1<<" "<<tx2<<" "<<ty1<<" "<<ty2<<endl;
if(tx1<=tx2&&ty1<=ty2)
{
dis1=tx2-tx1+1;
dis2=ty2-ty1+1;
sx-=dis1*dis2/2;
sy+=dis1*dis2/2;
if(((dis1*dis2)&1)&&(tx1+ty1)&1)sx-=1,sy+=1;
}
cout<<sx<<" "<<sy<<endl;
}
}