UVA1152_4 Values whose Sum is 0

中途相遇法,这题目总结后我感觉和第一篇博客很像,他们都取了中间,也许这就是二分的魅力吧

这题题意就是从ABCD四个集合中选四个元素使他们的和为0

题意很简单,但是实现起来很容易超时,不能一个一个枚举

然后就想到了枚举两个,那么新生成EF两个集合大小为n方,然后如何查找?

最容易想到的就是用map标记,但汝佳说了这会超时,我不信,试了一发,超时了!!!

除了用map还能用什么呢,联想到之前那个UVA对称的题目,我们可以sort一下,然后查找e的相反数时候,二分查找-e,记住,找到还不行,有可能存在多个-e.所以upper_bound-lower_bound 就可以了,然后就这样过了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#include<cstdlib>
#include<algorithm>
#include<stack>
#include<map>
#include<queue>
#include<vector>
using namespace std;
int t,n,a,b,c,d,kase,cnt;
int num[4][4040],sum1[16000040],sum2[16000040];
map<int,int> list;
int main(){
   // freopen("in.txt","r",stdin);
   // freopen("out.txt","w",stdout);
    kase=0;
    cin>>t;
    while(t--){
        memset(num,0,sizeof num);
        memset(sum1,0,sizeof sum1);
        memset(sum2,0,sizeof sum2);
        cnt=0;
        if(kase++) cout<<"\n";
        cin>>n;
        for(int i=0;i<n;i++)
            scanf("%d%d%d%d",&num[0][i],&num[1][i],&num[2][i],&num[3][i]);
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                sum1[i*n+j]=num[0][i]+num[1][j];
                sum1[i*n+j]=-sum1[i*n+j];
            }
        }
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                sum2[i*n+j]=num[2][i]+num[3][j];
                
            }
        }
        sort(sum1,sum1+n*n);
        sort(sum2,sum2+n*n);
        int end=n*n,pos1=0,pos2=0;
        for(int i=0;i<end;i++){
            pos1 = lower_bound(sum2+pos1,sum2+end,sum1[i]) -sum2;
            pos2 = upper_bound(sum2+pos1,sum2+end,sum1[i]) -sum2;
            if(pos1==end) break;
            cnt+=pos2-pos1;
            pos1=max(pos1-1,0);
        }
        cout<<cnt<<endl;
    }
        return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值