1. 程式人生 > >【容斥+矩陣面積並】Masha and two friends

【容斥+矩陣面積並】Masha and two friends

題目連結

題意:

題目很長,但是其實題意非常簡單,首先是給定一個n*m的方格,然後黑白相間,其中左下角是白色。

然後有兩個人愛塗色,然後A先塗色把他所選中的地方塗成白色,然後B把他選中的地方塗成黑色。

然後問最後的情況白色格子有多少,黑色格子有多少?


小結:

其實這個題以前是做過的,但是自己卻沒有把這個題補回來,然後這個題就一直被遺忘了,其實就是一個簡單的容斥,就是找一個面積並的過程比較煩一點,其餘都是很簡單的容斥。很好解釋。

題解:

前提工作:設定一個函式,只要知道左下角的位置是黑色還是白色,然後知道這個選中的方格的大小,然後就可以算出裡面的黑格和白格算出來。

然後進行容斥:

定義:F1  為 A選中的方框,F2 為 B選中的方框,F3為矩陣的面積並

白格=原來白格+F1黑-F2白-F3黑色

黑格=原來黑格-F1黑+F2白+F3白色

主要是求出這個矩陣的面積並首先是求出兩個長方形的排序,

然後把它們的交點,通過最大最小值比較得出兩個交點,

然後就是把這個矩陣算出來F3的黑格。


然後就是自己寫程式碼了:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
void Count_board(ll x1,ll y1,ll x2,ll y2,ll &black ,ll &white){
    ll sum=(y2-y1+1)*(x2-x1+1);
    black=(x1+y1)&1   ?(sum-1)/2+1:sum/2;
    white=(x1+y1)%2==0?(sum-1)/2+1:sum/2;
}
ll x[6],y[6],tx[4],ty[4],W,B;
ll n,m,w[4],b[4];
int main()
{
    int Q;
    scanf("%d",&Q);
    while(Q--){
        scanf("%lld%lld",&m,&n);
        scanf("%lld%lld%lld%lld",&x[0],&y[0],&x[1],&y[1]);
        scanf("%lld%lld%lld%lld",&x[2],&y[2],&x[3],&y[3]);
        Count_board(1,1,m,n,b[0],w[0]);
        Count_board(x[0],y[0],x[1],y[1],b[1],w[1]);
        Count_board(x[2],y[2],x[3],y[3],b[2],w[2]);
        for(int i=0;i<4;i++){
            tx[i]=x[i],ty[i]=y[i];
        }
        W=w[0]+b[1]-w[2];
        B=b[0]-b[1]+w[2];
        x[4]=max(x[0],x[2]);y[4]=max(y[0],y[2]);
        x[5]=min(x[1],x[3]);y[5]=min(y[1],y[3]);
        if(x[4]<=x[5]&&y[4]<=y[5]){
            Count_board(x[4],y[4],x[5],y[5],b[3],w[3]);
            W=W-b[3];
            B=B+b[3];
        }
        printf("%lld %lld\n",W,B);
    }
    return 0;
}