列表

详情


NC200040. So We Back In The Mine

描述

今晚是不同寻常的一晚,因为今晚是闪耀的钻石之夜 (the splendid diamonds night)!
在今晚,会有很多的钻石奇迹般地出现在地平线以下。

Vanis通过之前找到的地图,知道了钻石的出现情况,地图上说,如果将这个世界看做由一个个方块组成的,则可以从俯视地面的角度观察,以某块地面作为了坐标原点,之后以这块地面的正北方向作为y轴,以这块地面正东方向作为x轴,之后每块地面刚好有唯一的整数坐标与之对应,如作为坐标原点的地面方块的坐标为,其正东方向与正北方向相邻的地面方块坐标分别为。如下图所示:



坐标为的地面下,会产生块钻石(其中为最大值函数,取值为a与b二者中较大者。|a|表示取a的绝对值),Vanis想知道以为左下角坐标、以为右上角坐标所构成的矩形区域内的地下一共产生了多少块钻石。

形式化地说,坐标为的地面下会产生块钻石,Vanis想知道函数的值。

举个例子,如下图所示:


红色区域对应查询,查询结果为21。
黄色区域对应查询,查询结果为22。
蓝色区域对应查询,查询结果为6。

输入描述

第一行输入一个正整数q,表示总共会有q次询问。
之后输入q行,表示每次询问。每一行输入四个整数,依次是x_1, y_1,x_2,y_2,之间使用一个空格符分隔,表示要查询钻石数的矩形区域。

数据规范:
* .
* .
* .
* .
* 保证所有输入的数都是整数。

输出描述

对于每行询问,依次输出询问区域内的钻石数,使用一个整数表示,每个输出占一行。

注意用来存储答案的变量的数据类型,不能使用32位整型。
如果您使用C、C++,不能使用int类型(32位整型),请使用long long int类型(64位整型)。
如果您使用Java,不能使用int类型(32位整型),请使用long类型(64位整型)。
如果您使用Python2、Python3,请随意。。。

示例1

输入:

3
0 0 0 0
1 1 2 2
-2 -2 -1 -1

输出:

1
11
11

示例2

输入:

5
-20000 -20000 20000 -1
-20000 0 20000 20000
-20000 -20000 -1 20000
0 -20000 20000 20000
-20000 -20000 20000 20000

输出:

10668066690000
10668466750001
10668066690000
10668466750001
21336533440001

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 138ms, 内存消耗: 3556K, 提交时间: 2019-12-07 16:23:32

#include<iostream>
using namespace std;
typedef long long ll;
ll s[1<<16];
int q, x1, x2, y1, y2;
ll gt(ll x, ll y)
{
    if(x > y)
        swap(x, y);
    return s[x] + (x+1)*(x+3+y)*(y-x) / 2;
}
int main()
{
    s[0] = 1;
    for(int i = 1; i < 2e4+7; i++)
        s[i] = s[i-1] + (2*i+1) * (i+1);
    scanf("%d", &q);
    while(q-- > 0)
    {
        scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
        if(x2 <= 0)
        {
            swap(x1, x2);
            x1 = -x1, x2 = -x2;
        }
        if(y2 <= 0)
        {
            swap(y1, y2);
            y1 = -y1, y2 = -y2;
        }
        if(x1 > 0 && y1 > 0)
        {
            printf("%lld\n", gt(x2, y2) - gt(x1-1, y2) - gt(x2, y1-1) + gt(x1-1, y1-1));
        }
        else if(x1 > 0 && y1 <= 0)
        {
            printf("%lld\n", gt(x2, y2) - gt(x1-1, y2) + gt(x2, -y1) - gt(x1-1, -y1) - gt(x2, 0) + gt(x1-1, 0));
        }
        else if(x1 <= 0 && y1 > 0)
        {
            printf("%lld\n", gt(x2, y2) - gt(x2, y1-1) + gt(-x1, y2) - gt(-x1, y1-1) - gt(0, y2) + gt(0, y1-1));
        }
        else
        {
            printf("%lld\n", gt(x2, y2) + gt(-x1, y2) + gt(x2, -y1) + gt(-x1, -y1) - gt(0, x2) - gt(0, -x1) - gt(0, y2) - gt(0, -y1) + 1);
        }
    }
}

C++14(g++5.4) 解法, 执行用时: 232ms, 内存消耗: 8408K, 提交时间: 2019-12-09 16:10:21

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5+10;
ll q,a,b,c,d;
ll cal1(ll n)
{
	return n*(n+1)/2;
}
ll cal2(ll n)
{
	return n*(n+1)*(2*n+1)/6; 
}
ll pre(ll n,ll m)//(0,0)-(n,m)
{
	if(n<0||m<0)
	return 0;
	n++;m++;
	ll mi=min(n,m);
	ll ma=max(n,m);
	ll ans=cal2(mi)*2-cal1(mi);//(0,0)-(mi,mi)正方形
	ans+=mi*(cal1(ma)-cal1(mi));//剩余矩形 
	return ans; 
}
ll solve(ll a,ll b,ll c,ll d)//(a,b)-(c,d)
{
	return pre(c,d)+pre(a-1,b-1)-pre(c,b-1)-pre(a-1,d);
}
int main()
{
	scanf("%lld",&q);
	while(q--)
	{
		ll ans=0;
		scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
		if(c>=0&&d>=0)
		{
			if(a>=0&&b>=0)
			ans=solve(a,b,c,d);
			else if(a>=0&&b<0)
			ans=solve(a,0,c,d)+solve(a,1,c,-b);
			else if(a<0&&b>=0)
			ans=solve(0,b,c,d)+solve(1,b,-a,d);
			else if(a<0&&b<0)
			ans=solve(0,0,c,d)+solve(1,0,-a,d)+solve(0,1,c,-b)+solve(1,1,-a,-b);
		}
		else if(c>=0&&d<0)
		{
			if(a>=0)
			ans=solve(a,-d,c,-b);
			else if(a<0)
			ans=solve(0,-d,c,-b)+solve(1,-d,-a,-b);
		}
		else if(c<0&&d>=0)
		{
			if(b>=0)
			ans=solve(-c,b,-a,d);
			else if(b<0)
			ans=solve(-c,0,-a,d)+solve(-c,1,-a,-b);
		}
		else if(c<0&&d<0)
		ans=solve(-c,-d,-a,-b);
		printf("%lld\n",ans);
	}
}

上一题