暴力O(n4)超时。
思路1:二分。
枚举所有a+b(a属于A[],依次类推),把所有 a+b 记录下来放在一个数组sum中,对sum排序。然后枚举所有 -c-d ,在 sum 中二分查找有几个这样的值,用upper_bound() - lower_bound() 就是个数,累计到结果中。 O(n^2logn)
运行 2750ms
#include <cstdio>
#include <algorithm>
using namespace std;
#define LL long long int
#define maxn 4005
int T,n,A[maxn],B[maxn],C[maxn],D[maxn],sum[maxn*maxn];
int main()
{
//freopen("in.txt","r",stdin);
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for( int i=0; i<n; ++i )
{
scanf("%d%d%d%d",&A[i],&B[i],&C[i],&D[i]);
}
int c=0;
for( int i=0; i<n; ++i ){
for( int j=0; j<n; ++j ){
sum[c++]=A[i]+B[j];
}
}
sort(sum,sum+c);
LL ans=0;
for( int i=0; i<n; ++i ){
for( int j=0; j<n; ++j ){
ans+=upper_bound(sum,sum+c,-C[i]-D[j])-lower_bound(sum,sum+c,-C[i]-D[j]);
}
}
printf("%lld\n",ans);
if(T) printf("\n");
}
//fclose(stdin);
return 0;
}
思路2:哈希
还是和之前一样枚举 a+b ,只是这次不是放在数组 sum 中,而是hash映射到某一个值(出现次数)。枚举 -c-d 时直接通过 hash函数找到值,累计到结果。 O(n^2)
运行 490ms
哈希函数:
struct hash_mp{
static const int N = 0x7fffff;
int num[N],vis[N];
void clear(){
memset( vis,0,sizeof(vis) );
}
int& operator[](int k){
int i;
for( i=k&N; vis[i]&&num[i]!=k; i=(i+1)&N ) ;
num[i] = k;
return vis[i];
}
}hash1;
hash1[]并不用很大,但是它能处理的数却很大。这是因为重载了运算符[]。对于 k ,先通过位运算中的 & 将其控制在数组上限之内,不断哈希,如果hash1(k)的值已经被占用且存的不是这个值,说明这个位置被其他占了,只能继续哈希,直到找到空位,赋值,返回访问次数。
#include <cstdio>
#include <cstring>
using namespace std;
#define LL long long int
#define maxn 4005
int T,n,A[maxn],B[maxn],C[maxn],D[maxn];
struct hash_mp{
static const int N = 0x7fffff;
int num[N],vis[N];
void clear(){
memset( vis,0,sizeof(vis) );
}
int& operator[](int k){
int i;
for( i=k&N; vis[i]&&num[i]!=k; i=(i+1)&N ) ;
num[i] = k;
return vis[i];
}
}hash1;
int main()
{
//freopen("in.txt","r",stdin);
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for( int i=0; i<n; i++ )
scanf("%d%d%d%d",&A[i],&B[i],&C[i],&D[i]);
hash1.clear();
for( int i=0; i<n; i++ ){
for( int j=0; j<n; j++ ){
hash1[A[i]+B[j]]++;
}
}
LL ans=0;
for( int i=0; i<n; i++ ){
for( int j=0; j<n; j++){
ans+= hash1[-C[i]-D[j]];
}
}
printf("%lld\n",ans);
if(T) printf("\n");
}
//fclose(stdin);
return 0;
}