【什么是upper_bound 和 lower_bound】

简单来说lower_bound就是你给他一个非递减数列[first,last)和x,它给你返回非递减序列[first, last)中的第一个大于等于值x的位置。

而upper_bound就是你给他一个非递减数列[first,last)和x,它给你返回非递减序列[first, last)中的第一个大于值x的位置。

STL中实现这两种函数的算法就是二分。。。。。。

【upper_bound 和 lower_bound代码】

//STl中的lower_bound源代码
//这个算法中,first是最终要返回的位置
int lower_bound(int *array, int size, int key)
{
int first = 0, middle;
int half, len;
len = size; while(len > 0)
{
half = len >> 1;
middle = first + half;
if(array[middle] < key)
{
first = middle + 1;
len = len-half-1; //在右边子序列中查找
}
else
len = half; //在左边子序列(包含middle)中查找
}
return first;
}
//——————————upper_bound——————————————————
int upper_bound(int *array, int size, int key)
{
int first = 0, len = size-1;
int half, middle; while(len > 0){
half = len >> 1;
middle = first + half;
if(array[middle] > key) //中位数大于key,在包含last的左半边序列中查找。
len = half;
else{
first = middle + 1; //中位数小于等于key,在右半边序列中查找。
len = len - half - 1;
}
}
return first;
}
//______________End___________________________________________________________

【POJ 2785】

【题目原文】

The SUM problem can be formulated as follows: given four lists A, B, C, D of integer values, compute how many quadruplet (a, b, c, d ) ∈ A x B x C x D are such that a + b + c + d = 0 . In the following, we assume that all lists have the same size n .

【题目大意】

给定各有n个整数的4个数列A,B,C,D。要从每一个数列中各去出一个数,使四个数的和为0.求出这样组合的个数。(当同一数列中有相同数字时按不同数字看待——博主注)

【输入描述】

有n行,一行4个数,分别是A[i],B[i],C[i],D[i]

【输入样例】

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

【输出描述】

一个数

【输出样例】

5

【博主注释】

有5种情况,分别是-45-27+42+30    26+30-10-46    -32+22+56-46    -32+30-75+77    -32-54+56+36

【题目分析】

我们把这些数对半分成AB与CD考虑。先从AB中取出a[i],b[i]后,为了使总和为0则需要从CD中取出c[i]+d[i]=a[i]-d[i]。因此将这些情况枚举出来,再用upper_bound和lower_bound进行二分即可。时间复杂度为O(n^2 logn)

【代码】

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=4001;
int n;
int a[maxn],b[maxn],c[maxn],d[maxn];
int cd[16000001];
int lower_bound(int *array, int size, int key)
{
int first = 0, middle;
int half, len;
len = size;
while(len > 0)
{
half = len >> 1;
middle = first + half;
if(array[middle] < key)
{
first = middle + 1;
len = len-half-1; //在右边子序列中查 找
}
else
len = half; //在左边子序列(包含middle)中查找
}
return first;
}
int upper_bound(int *array, int size, int key)
{
int first = 0, len = size-1;
int half, middle;
while(len > 0)
{
half = len >> 1;
middle = first + half;
if(array[middle] > key) len = half; //中位数大于key,在包含last的左半边序列中查找.
else
{
first = middle + 1; //中位数小于等于key,在右半边序列中查找。
len = len - half - 1;
}
}
return first;
}
int main()
{
cin>>n;
for(int i=0;i<n;i++) cin>>a[i]>>b[i]>>c[i]>>d[i];
//for(int i=0;i<n;i++) cin>>b[i];
//for(int i=0;i<n;i++) cin>>c[i];
//for(int i=0;i<n;i++) cin>>d[i];
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++) cd[i*n+j]=c[i]+d[j];
}
sort(cd,cd+n*n);
long long res=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
int CD=-(a[i]+b[j]);
res+=upper_bound(cd,cd+n*n,CD)-lower_bound(cd,cd+n*n,CD);
}
}
cout<<res;
return 0;
}

  

【刷题记录】 && 【算法杂谈】折半枚举与upper_bound 和 lower_bound的更多相关文章

  1. $2019$ 暑期刷题记录1:(算法竞赛DP练习)

    $ 2019 $ 暑期刷题记录: $ POJ~1952~~BUY~LOW, BUY~LOWER: $ (复杂度优化) 题目大意:统计可重序列中最长上升子序列的方案数. 题目很直接的说明了所求为 $ L ...

  2. PKUWC&SC 2018 刷题记录

    PKUWC&SC 2018 刷题记录 minimax 线段树合并的题,似乎并不依赖于二叉树. 之前写的草率的题解在这里:PKUWC2018 minimax Slay the Spire 注意到 ...

  3. DP刷题记录(持续更新)

    DP刷题记录 (本文例题目前大多数都选自算法竞赛进阶指南) TYVJ1071 求两个序列的最长公共上升子序列 设\(f_{i,j}\)表示a中的\(1-i\)与b中色\(1-j\)匹配时所能构成的以\ ...

  4. 刷题记录:[De1CTF 2019]Giftbox && Comment

    目录 刷题记录:[De1CTF 2019]Giftbox && Comment 一.知识点 1.sql注入 && totp 2.RCE 3.源码泄露 4.敏感文件读取 ...

  5. DP刷题记录

    目录 dp刷题记录 codeforces 706C codeforces 940E BZOJ3997 POJ2279 GYM102082B GYM102082D codeforces132C L3-0 ...

  6. 刷题记录:[GWCTF 2019]枯燥的抽奖

    目录 刷题记录:[GWCTF 2019]枯燥的抽奖 知识点 php伪随机性 刷题记录:[GWCTF 2019]枯燥的抽奖 题目复现链接:https://buuoj.cn/challenges 参考链接 ...

  7. 2021.12.19 eleveni的刷题记录

    2021.12.19 eleveni的刷题记录 0. 本次记录有意思的题 0.1 每个点恰好经过一次并且求最小时间 P2469 [SDOI2010]星际竞速 https://www.luogu.com ...

  8. 2021.12.16 eleveni的刷题记录

    2021.12.16 eleveni的刷题记录 1. 数论 https://www.luogu.com.cn/problem/P2532 1.1卡特兰数 https://www.luogu.com.c ...

  9. PE刷题记录

    PE刷题记录 PE60 / 20%dif 这道题比较坑爹. 所有可以相连的素数可以构成一张图,建出这张图,在其中找它的大小为5的团.注意上界的估算,大概在1W以内.1W内有1229个素数,处理出这些素 ...

随机推荐

  1. js传入参数为字符串问题

    示例: var device_mac="11qweq234ert"; //第一种方式会报错:Onclick SyntaxError: identifier starts immed ...

  2. Learning Spark 第四章——键值对处理

    本章主要介绍Spark如何处理键值对.K-V RDDs通常用于聚集操作,使用相同的key聚集或者对不同的RDD进行聚集.部分情况下,需要将spark中的数据记录转换为键值对然后进行聚集处理.我们也会对 ...

  3. break与continue的区别

    break       在while.for.do...while.while循环中使用break语句退出当前循环,直接执行后面的代码. continue   的作用是仅仅跳过本次循环,而整个循环体继 ...

  4. 2016 Google code jam 答案

    二,RoundC import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileNotFoundE ...

  5. MAC实用的小工具

    一.XtraFinder(右键菜单扩展) http://www.xuebuyuan.com/173454.html http://www.mamicode.com/info-detail-111618 ...

  6. swing中JTable的使用方法

    public static void main(String[] args) { Student s1 = new Student("张三", "001", 0 ...

  7. 企业号查询部门id(改版后)

    1.搜索部门,输入"名称" 2.在后面可以查到部门ID

  8. DataTable导出到Excel

    简单的导出到Excel中: 代码如下: using System; using System.Collections.Generic; using System.Data; using System. ...

  9. SQL 查看数据库的列数

    查询表名为History的所有列名 1 select name from syscolumns where id=object_id('History') 查询表名为History的所有列名个数   ...

  10. 建表过程-列名&列类型&修改表小试题C

    #新增数据 INSERT INTO goods VALUES(10,'豆豆','男',85.2,'2016-12-14',5000.36,'2016-12-14 12:05:06','高') INSE ...