当前位置: 首页 > article >正文

四个数列(二分查找)

问题描述

ZJM 有四个数列 A,B,C,D,每个数列都有 n 个数字。ZJM 从每个数列中各取出一个数,他想知道有多少种方案使得 4 个数的和为 0。

当一个数列中有多个相同的数字的时候,把它们当做不同的数对待。

请你帮帮他吧!

Input

第一行:n(代表数列中数字的个数) (1≤n≤4000)

接下来的 n 行中,第 i 行有四个数字,分别表示数列 A,B,C,D 中的第 i 个数字(数字不超过 2 的 28 次方)

Output

输出不同组合的个数。

Sample input

6
-45 22 42 -16
-41 -27 56 30
-36 53 -37 77
-36 30 -75 -46
26 -38 -10 62
-32 -54 -6 45

Sample output

5

Hint

样例解释: (-45, -27, 42, 30), (26, 30, -10, -46), (-32, 22, 56, -46),(-32, 30, -75, 77), (-32, -54, 56, 30).

解题思路

乍一看是一个暴力枚举题目,但是注意数据范围,n<=4000的范围肯定不能四重循环来枚举。

我们采用先枚举A和B,得到A和B的和ab数组,然后枚举C和D,在枚举C和D的时候,计算它的相反数在ab数组中出现的次数。这样时间复杂度就可以控制在 O ( n 2 ) O(n^2) O(n2)

那么如何统计次数呢?

map!必须map!key值是A和B中枚举元素的和,对应的element是次数,提交!TLE!很明显,map耗时有点严重。。。

然后我们的unordered_map登场了!这样一个无序map,其耗时比普通的map要少很多!提交!CE!看来这题不支持C++11。。。

后来想起了(翻ppt找到了)学长上课讲的东西,统计出现的次数我们可以先用sort排序,然后二分查找,查找一个数在ab数组中第一次和最后一次出现的位置,做差加一后就是次数。顺利AC。

完整代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <climits>
#include <algorithm>
#include <queue>
#include <vector>
#include <map>
using namespace std;const int maxn=4000+10;
int a[maxn],b[maxn],c[maxn],d[maxn],n,ans,ab[maxn*maxn],index1;
int getint()
{int x=0,s=1;char ch=' ';while(ch<'0' || ch>'9'){ch=getchar();if(ch=='-') s=-1;}while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*s;
}
int findfirst(int x)//找到x的第一个位置,找不到返回-1
{int left=1,right=index1,anstemp=-1;while(left<=right){int mid=(left+right)>>1;if(ab[mid]==x){anstemp=mid;right=mid-1;}else if(ab[mid]<x) left=mid+1;else right=mid-1;}return anstemp;
}
int findend(int x)//找到x的最后一个位置,找不到返回-1
{int left=1,right=index1,anstemp=-1;while(left<=right){int mid=(left+right)>>1;if(ab[mid]==x){anstemp=mid;left=mid+1;}else if(ab[mid]>x) right=mid-1;else left=mid+1;}return anstemp;
}
int main()
{
//    ios::sync_with_stdio(false);
//    cin.tie(0);n=getint();for (int i=1; i<=n; i++)a[i]=getint(),b[i]=getint(),c[i]=getint(),d[i]=getint();for (int i=1; i<=n; i++)for (int j=1; j<=n; j++)ab[++index1]=a[i]+b[j];sort(ab+1,ab+1+index1);for (int i=1; i<=n; i++)for (int j=1; j<=n; j++){int temp=c[i]+d[j];int first=findfirst(-temp);int end=findend(-temp);if(first!=-1)//存在ans+=end-first+1;}printf("%d\n",ans);return 0;
}
http://www.lryc.cn/news/2419779.html

相关文章:

  • IoU,GIoU,DIoU、CIoU详解
  • System.ArgumentException HResult=-2147024809 Message=参数无效。 Source=System.Drawing
  • 标志位寄存器与CF、OF标志位的区分
  • 史上可以针对大部分对于鼠标右键菜单的设置
  • 常用协议对应的端口号
  • Javaweb开发项目之JS知识(JavaScript)
  • 日本推出罩杯测量APP,罩杯大小一夹便知!
  • AFL实战
  • 中国家装水管十大品牌排行榜:联塑、日丰、金牛、弗锐德、美尔固等品牌上榜
  • 字体下载_ps字体打包下载,送你1.15G+316款可用字体
  • 8005端口导致的阿里云上的tomcat无法外部访问
  • 2021-09-18堡垒机
  • SuperMap iMobile for Android许可介绍
  • Phoenix 的 thick Client 和 thin Client
  • Actix-Web构建一个简单的HTTP服务器
  • 51单片机原理以及接口技术(四)--80C51的程序设计
  • greensock下载_GreenSock动画平台初学者指南
  • 手把手叫你做ToDoList
  • 解密:2012世界末日其实是个大骗局
  • 算法设计与分析——背诵知识点合集
  • 霍夫曼(Huffman)编码算法详解之C语言版
  • 强度理论介绍和惯性矩推导
  • 数据库性能监控策略:如何监控数据库性能
  • 基本概念:子域名和域
  • 【HTML基础】HTML基本语法
  • 【CSDN软件工程师能力认证学习精选】吐血整理!140 种 Python 标准库、第三方库和外部工具都有了
  • linux驱动开发扩展--字符设备注册详解
  • 多线程之线程间通讯
  • (4)pokeman_用图片对模型进行测试
  • 什么是TTL电平,什么是CMOS电平