HRBUST 1293 map||二分
2013-10-07 22:56
344 查看
有n个整数,给定一个数x,从n个数中取两个数,使得和刚好为x,问有多少种取法。0 < n <= 100000
2层枚举必然超时..
map
用map的话,一层枚举,枚举到每个数str[i]即可知道x-str[i]出现与否以及出现次数,统计即可
如果str[i]*2==x的话需要特殊处理下。
二分方法
首先把数据升序排列,然后枚举.
对于每一个str[i],key=x-str[i],只需要在i之后,n-1之前找到2个下标st和ed
st是第一个str[y]>=key的y,ed是第一个str[y]>key的y,
最后判断一下 str[st]==key&&str[ed-1]==key,如果是,tot则需要加上ed-st
统计的时候需要用long long ,因为50000*50000就超int了
2层枚举必然超时..
map
用map的话,一层枚举,枚举到每个数str[i]即可知道x-str[i]出现与否以及出现次数,统计即可
如果str[i]*2==x的话需要特殊处理下。
二分方法
首先把数据升序排列,然后枚举.
对于每一个str[i],key=x-str[i],只需要在i之后,n-1之前找到2个下标st和ed
st是第一个str[y]>=key的y,ed是第一个str[y]>key的y,
最后判断一下 str[st]==key&&str[ed-1]==key,如果是,tot则需要加上ed-st
统计的时候需要用long long ,因为50000*50000就超int了
#include<stdio.h> #include<algorithm> using namespace std; int main(){ long long str[100005],tp; int mid; int n,m,left,right,st,ed; while(scanf("%d %d",&n,&m)!=EOF){ for(int i=0;i<n;i++)scanf("%lld",&str[i]); long long tot=0; sort(str,str+n); for(int i=0;i<n;i++){ tp=m-str[i]; left=i+1,right=n-1; while(right>=left){ mid=(left+right)/2; if(str[mid]<tp)left=mid+1; else right=mid-1; }st=left; left=i+1,right=n-1; while(right>=left){ mid=(left+right)/2; if(str[mid]<=tp)left=mid+1; else right=mid-1; }ed=left; if(str[st]==tp&&str[ed-1]==tp){ tot+=ed-st; } } printf("%lld\n",tot); } return 0; }
相关文章推荐
- 终端快捷键
- SharePoint自动化部署,利用PowerShell 导出/导入AD中的用户
- java中|和||的区别
- MongoDB 学习笔记(二):shell中执行增删查改
- C语言位段
- 网易游戏面试
- 哥德巴赫猜想近似证明问题
- Oracle rollup 关键字用法简介.
- eclipse 下cocos2d-x游戏环境搭建及编译与运行
- 这是说好的心得体会,欧也~
- 图算法 最小生成树 Prim算法 Kruskal算法
- 用户登入界面保存用户名和密码
- 求二叉树的深度和宽度
- LAMP平台--部署Discuz论坛
- arm-linux-androideabi-gcc 4.8的选项分析
- linux输入子系统
- 百度2014校园招聘客户端开发笔试题(南京站)
- !!!Cryptology
- Spring MVC 框架搭建及详解
- Eclipse快捷键大全(转载)