题目链接:POJ - 2785 : 4 Values whose Sum is 0
题目大意:四组数中各选一个使满足a+b+c+d=0,问有多少种组合方式
思路:先a+b和c+d组合分别得到一个数组,排序后可以用二分,但这里需要注意一点,前面我们用二分是查找存不存在使满足条件的组合,很简单,而这里是要我们计算有多少种组合,所以二分的时候要先用二分查找有序数组中满足条件的第一个值,然后向后搜索并累加可能的组合。
还有一种更简便的做法是直接用STL中现有的lower_bound、upper_bound,二者相减就是中间相同元素的个数,其实质还是二分查找。
AC代码:
- 二分
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define maxn 4005
int a[maxn],b[maxn],c[maxn],d[maxn],ab[maxn*maxn],cd[maxn*maxn];
int ans,k;
void cnt(int x)
{
int l=0,r=k-1,mid;
while(l<r)
{
mid=(l+r)/2;
if(cd[mid]<x) l=mid+1;
else r=mid;
}
while(cd[l]==x && l<k)//从满足条件的第一个元素往后搜索
{
ans++;
l++;
}
}
int main()
{
int n;
scanf("%d",&n);
for(int i=0; i<n; i++)
scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
k=0;
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
{
ab[k]=-(a[i]+b[j]);
cd[k++]=c[i]+d[j];
}
sort(cd,cd+k);
ans=0;
for(int i=0; i<k; i++)
cnt(ab[i]);
printf("%d\n",ans);
return 0;
}
- 上下界函数
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 4005;
int a[N], b[N], c[N], d[N], s[N * N];
int main()
{
int m,k,n,ans;
ans=m=0;
scanf("%d",&n);
for(int i=0; i<n; i++)
scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
s[m++]=a[i]+b[j];
sort(s,s+m);
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
{
k=-c[i]-d[j];
ans+=(upper_bound(s,s+m,k)-lower_bound(s,s+m,k));
}
printf("%d\n",ans);
return 0;
}