妞妞的问题

1.【题目描述】

  妞妞公主新得到一块白色棋盘。这块棋盘共有n行m列,任意相邻的两个格子都是不同的颜色(黑或白),坐标位(1,1)的格子是白色的。
  这一天牛牛来看妞妞公主时,牛牛公主正望着棋盘发呆。牛牛看妞妞公主闷闷不乐的样子,便对妞妞公主说:“只要你告诉我n和m,我能马上算出黑色方块的白色方块的数量。”
  “这太简单了。”妞妞公主想了一会,“我会在这n行m列中选择一个左下角坐标位(x0,y0)。右上角坐标为(x1,y1)的矩形,把这个矩形里的共(x1-x0+1)*(y1-y0+1)个方块全部涂白。你还能马上算出黑色方块和白色方块的数量吗?”
  “这太简单了。”牛牛自信一笑,“你还可以在执行涂白操作后再选择一个左下角坐标为(x2,y2),右上角坐标为(x3,y3)的矩形,把这个矩形里的方块全部涂黑。我依然能马上算出黑色方块和白色方块的数量。”
  妞妞公主终于惊讶地睁大了眼睛,于是抛出了她的T次提问。
  聪明的牛牛当然会做了,但是他想把这个问题交给你,请帮牛牛算出每次提问棋盘的黑白方块数目吧。

输入描述:
第一行一个整数T,表示妞妞公主一共提问了T次。
接下来3T行,
第(1+3i)行两个整数n,m。表示第i次提问时棋盘的大小;
第(2+3i)行四个整数x0,x1,y0,y1。表示第i次提问时涂白操作选取的两个坐标。
第(3+3i)行四个整数x2,y2,x3,y3。表示第i次提问时涂黑操作选取的两个坐标。
1<=T<=10000,1<=x<=n<=1000000000,1<=y<=m<=1000000000,x0<=x1,y0<=y1,x2<=x3,y2<=y。

输出描述:
共T行,每行两个整数分别表示白色方块的数量和黑色方块的数量。

输入样例:
3
1 3
1 1 1 3
1 1 1 3
3 3
1 1 2 3
2 1 3 3
3 4
2 1 2 4
1 2 3 3
输出样例:
0 3
3 6
4 8

2.【代码】(具体分析见代码注释)
/*
妞妞的问题

3
1 3
1 1 1 3
1 1 1 3
3 3
1 1 2 3
2 1 3 3
3 4
2 1 2 4
1 2 3 3
*/
#include<bits/stdc++.h>

using namespace std;

long long x[8], y[8];    //每次选择的坐标
int main()
{
	int T;    //询问次数
	long long n, m;    //初始棋盘大小
	long long black, white;    //黑白方块的数量
	long long a, b, c, d, e;    //重复范围坐标

	scanf_s("%d", &T);
	while (T--)
	{
		scanf_s("%lld%lld", &n, &m);
		black = n*m / 2;
		white = n*m - black;

		for (int i = 0; i < 4; i++)    //输入4个范围坐标
		{
			scanf_s("%lld%lld", &x[i], &y[i]);
		}

		if ((x[0] + y[0]) & 1)    //选择的第一个区域,如果左下角是一个黑色方格
		{
			d = ((x[1] - x[0] + 1)*(y[1] - y[0] + 1) + 1) / 2;    //偶数方格,不影响;奇数方格,会多出1个,也就是说第1次变换,黑色方格会多减去1个
		}
		else
		{
			d = (x[1] - x[0] + 1)*(y[1] - y[0] + 1) / 2;
		}
		white += d;    //白色方块增加d
		black -= d;    //黑色方块减少d

		if ((x[2] + y[2]) & 1)    //选择的第二个区域,如果左下角是一个黑色方格
		{
			d = (x[3] - x[2] + 1)*(y[3] - y[2] + 1) / 2;
		}
		else
		{
			d = ((x[3] - x[2] + 1)*(y[3] - y[2] + 1) + 1) / 2;    //偶数方格,不影响;奇数方格,会多出1个,也就是说第2次变换,白色方格会多减去1个
		}
		white -= d;    //白色方块减少d
		black += d;    //黑色方块增加d

		/*计算重叠部分*/
		a = max(x[0], x[2]);
		b = max(y[0], y[2]);
		c = min(x[1], x[3]);
		d = min(y[1], y[3]);

		if (c < a || d < b)    //无重复区域
		{
			e = 0LL;
		}
		else
		{
			if ((a + b) & 1)    //重复区域,如果左下角是一个黑色方格
			{
				e = ((c - a + 1)*(d - b + 1) + 1) / 2;    //白色方块增加的数目,黑色方块减少的数目
			}
			else
			{
				e = (c - a + 1)*(d - b + 1) / 2;
			}
			white -= e;    //白色方块减少d(减去重复范围内白色方块增加的数目)
			black += e;    //黑色方块增加d
		}
		printf("%lld %lld\n", white, black);
	}
	return 0;
}
3.【运行结果】

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值