Problem Description
现在就让我们来大胆地畅想2050。我们乘坐着无人驾驶的飞行汽车,驰骋在城市的街头,感受着都市的繁华。
我们看到了一栋高楼大厦,大厦的墙面可以看做一个 W×H 的矩形,我们把它的左下角当成(0,0),右上角当成(W,H)。上面分布着一些LED灯,这些LED灯与地面呈45度倾斜,并且从矩形的边界延伸到另一边界,把大厦分成了若干个区域。我们想数一下这个图里面存在多少个与地面成45度角的矩形,其中四条边都是LED灯的一部分。
Input
第一行一个正整数 T (T≤10) 表示数据组数。
对于每组数据,第一行 W,H,n,m (1≤W,H≤109,0≤n,m≤103) 表示矩形的长和宽,以及两种方向的LED灯的个数。
接下来一行 n 个整数c (1≤c≤W+H−1),表示这个LED灯可以表示成 x+y=c 的形式,保证 c 两两不同。
接下来一行 m 个整数 c (1−H≤c≤W−1),表示这个LED灯可以表示成 x−y=c 的形式,保证 c 两两不同。
Output
对于每组数据,输出一个整数表示答案,由于答案可能很大,对 109+7 取模。
Sample Input
1 21 12 6 5 4 8 14 20 26 30 -6 -1 2 10 14
Sample Output
19
Source
Test Contest
思路:感觉榜单被带歪了,其实这道题不是很难。看图:
因此我们我们考虑对c1的序列进行排序,任意选取两个c2的值,在c1中二分查询一个满足上述不等式的区间[l,r],(因此要满足r>l)那么在上述区间内任意选择两个c1都和这两个c2都能构成满足题意的解,因此对答案的贡献是:(r-l)*(r-l+1)/2。
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
ll W,H,n,m;
ll a[1005];
ll b[1005];
const int MOD=1e9+7;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%lld %lld %lld %lld",&W,&H,&n,&m);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
for(int j=1;j<=m;j++)
scanf("%lld",&b[j]);
sort(a+1,a+1+n);
sort(b+1,b+1+m);
ll l,r;
ll low1,high1,low2,high2;
ll re=0;
for(int i=1;i<m;i++)
{
low1=max(b[i],-b[i]);
high1=min(2*W-b[i],2*H+b[i]);
for(int j=i+1;j<=m;j++)
{
low2=max(b[j],-b[j]);
high2=min(2*W-b[j],2*H+b[j]);
low2=max(low2,low1);
high2=min(high2,high1);
l=lower_bound(a+1,a+1+n,low2)-a;
r=upper_bound(a+1,a+1+n,high2)-a-1;
if(r>l)
re=(re+(r-l+1)*(r-l)/2)%MOD;
}
}
printf("%lld\n",re);
}
return 0;
}