HDU - 6496 大厦 暴力+二分

题目链接:https://cn.vjudge.net/problem/HDU-6496

现在就让我们来大胆地畅想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

题解:我们枚举第一组中的两个c1,然后确定c2的可取范围,在第二组中找出合适的x个,C(x,2)即使当前组的答案,               注意如果找的的范围(l,r),  当l>r , 即可continue

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
int w,h,n,m;
int c1[1010],c2[1010];
pair<int,int> cul(int p)
{
	pair<int,int> res(1,1);
	int x,y;
	x=max(0,c1[p]-h);
	y=min(h,c1[p]);
	res.first=x-y;
	
	x=min(w,c1[p]);
	y=max(0,c1[p]-w);
	res.second=x-y;
	return res;
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d%d%d",&w,&h,&n,&m);
		for(int i=1;i<=n;i++)scanf("%d",&c1[i]);
		for(int i=1;i<=m;i++)scanf("%d",&c2[i]);
		sort(c1+1,c1+1+n);
		sort(c2+1,c2+1+m);
		int minn,maxx;
		ll ans=0;
		pair<int,int> t1,t2;
		int p1,p2;
		int l,r;
		for(int i=1;i<=n;i++)
		{
			t1=cul(i);
		//	cout<<t1.first<<" "<<t1.second<<endl;
			for(int j=i+1;j<=n;j++)
			{
				
				t2=cul(j);
			//	cout<<t1.first<<" "<<t1.second<<" "<<t2.first<<" "<<t2.second<<endl;
				l=max(t1.first,t2.first);
				r=min(t1.second,t2.second);

				p1=lower_bound(c2+1,c2+1+m,l)-c2;
				p2=upper_bound(c2+1,c2+1+m,r)-c2;
				p2--;
				if(p2<p1) continue;
			//	cout<<p1<<" "<<p2<<" "<<l<<" "<<r<<endl; 
				ans+=max((ll)(p2-p1+1)*(p2-p1+1-1)/2,0LL);
				ans%=mod;
			}
		}
		printf("%lld\n",ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/mmk27_word/article/details/89333069