题目链接
http://poj.org/problem?id=2785
解题思路
原来学长大致说过思路,两两一组,求和,判断两组是不是能相加和为0;
当时只是停留在思路方面,我就纳闷,两数一组得到两组n*n个数的数,再将两组数的每个数相加判断是否为0的时间复杂度不还是n^4,和不分组的时间复杂度没什么区别。这次看别人题解才知道原来是可以优化的。
由于计算 4 个数的和并不好计算,因此可以使用分治的思想,将 4 组数分为两组,然后每组再分别计算和,最后对两组合进行排序,让正数与负数相加判断是否为 0 即可
AC代码
#include<iostream> #include<algorithm> #define ll long long #define x first #define y second const int N=4100; const int inf=0x3f3f3f3f; using namespace std; bool cmp(int a,int b) { return a>b; } int n,cnt,p[N*N],q[N*N],a[N],b[N],c[N],d[N],ans; int main() { cin>>n; //一列一组输入 for(int i=1;i<=n;i++) cin>>a[i]>>b[i]>>c[i]>>d[i]; //分成两组p,q for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) ++cnt,p[cnt]=a[i]+b[j],q[cnt]=c[i]+d[j]; sort(p+1,p+cnt+1);//从小到大排序 sort(q+1,q+cnt+1,cmp);//从大到小排序 int j=1; //优化核心 for(int i=1;i<=cnt;i++) { while(j<=cnt && p[i]+q[j]>0) j++; if(j>cnt) break; int k=j; //一个p[i]可能对应多个q[j]相加=0 while(k<=cnt && p[i]+q[k]==0) ans++,k++; } cout<<ans<<endl; }