这道题给我最大的启示是:不要乱用ceil函数,在位数接近16位的情况下!

这道题只需要算一种颜色的格子,然后就得出这个公式:白色格子数=原来白色格子的总数-第一个格子白色总数-第二个格子白色总数+重叠部分白色的总数+第一个格子的面积-重叠部分的总面积

再有就是在算重叠部分的时候左下坐标取max,右上坐标取min

在计算面积的时候由于精度失真不能用ceil,于是在左下角为白色且格子个数为奇数的时候总面积/2+1,其余时候/2.

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll cal(int x1,int y1,int x2,int y2)
{
    if( (x1+y1)%2==0&&1LL*(x2-x1+1)*(y2-y1+1)%2==1 )
    {
        return 1LL*(x2-x1+1)*(y2-y1+1)/2+1;
    }
    else
    {
        return 1LL*(x2-x1+1)*(y2-y1+1)/2;
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        int x1,y1,x2,y2;
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        int x3,y3,x4,y4;
        scanf("%d%d%d%d",&x3,&y3,&x4,&y4);
        ll res=cal(1,1,m,n)-cal(x1,y1,x2,y2)-cal(x3,y3,x4,y4)+1LL*(x2-x1+1)*(y2-y1+1);
        if( x2<x3||x4<x1||y1>y4||y2<y3 );
        else
        {
            ll x5=max(x1,x3),y5=max(y1,y3),x6=min(x2,x4),y6=min(y2,y4);
            res+=( cal(x5,y5,x6,y6)-(x6-x5+1)*(y6-y5+1) );
        }
        printf("%lld %lld\n",res,1LL*n*m-res);
    }
}
View Code