Difference in two ways of using lower_bound [C++]std::set::lower_bound与std::lower_bound
缘起:Codeforces Round #555 (Div. 3), problem: (E) Minimum Array 这道题目难度不大,大概在div2 C题左右
但是有个关键点就是stl中lowerbound和set自带的lowerbound差别,
很naive的我想着这两个都是o(logn)的,事实上,t了无数发后才发现标程是 s.lower_bound(x)而我是(s.begin(),s.end(),x) 差别是我的是o(n),标程是logn级别的
set输入时已经建好树 而模板lowerbound要多一个类似建树的过程
可以简单的记住 algorithm的是通用的的lower_bound算法 set的是专有的s.lower_bound(x)算法 肯定set快一点
STL的设计是通用的和灵活的。
有很多容器,它们都需要支持通用操作,比如遍历元素、排序、查找元素等等。因此,STL并没有在所有容器中实现多个方法container.sort(),而是提供了一个统一的函数std::sort(),它可以用于对不同的容器进行排序,而不是在所有容器中实现多个方法container.sort(),其中大多数方法都使用相同的算法。函数std::lower_bound()也是如此。
然而,由于容器的内部模型,并不是所有的容器都使用相同的算法。例如,不能像在vector中那样以随机顺序访问list中的元素。对于这种情况,有专门为容器设计的方法。因此list有方法list::sort(),它使用特定于链表结构的算法。
set和lower_bound()也是一样。有一个统一的函数std::lower_bound(),它在随机访问迭代器上的O(logN)中工作,在其他迭代器上的O(N)中工作。容器std::set具有双向迭代器,不能提供对其成员的随机访问。所以统一的std::lower_bound()在O(N)中工作。而容器集是二叉搜索树,可以使用不同的算法在O(logN)中找到下界,具体针对std::set的内部结构。它在方法集::lower_bound()中实现,在O(logN)中工作。
附上AC代码
// luogu-judger-enable-o2
#include<bits/stdc++.h>
#include<unordered_set>
#define rg register ll
#define inf 2147483647
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define ll long long
#define maxn 200005
const double eps = 1e-8;
using namespace std;
inline ll read()
{
char ch = getchar(); ll s = 0, w = 1;
while (ch < 48 || ch>57) { if (ch == '-')w = -1; ch = getchar(); }
while (ch >= 48 && ch <= 57) { s = (s << 1) + (s << 3) + (ch ^ 48); ch = getchar(); }
return s * w;
}
inline void write(ll x)
{
if (x < 0)putchar('-'), x = -x;
if (x > 9)write(x / 10);
putchar(x % 10 + 48);
}
ll n, a[maxn], ans[maxn], minn = maxn;
multiset<ll>p;
int main()
{
n = read();
for (rg i = 1; i <= n; i++)a[i] = read();
for (rg i = 1; i <= n; i++)
{
ll x = read();
minn = min(x, minn);
p.insert(x);
}
for (rg i = 1; i <= n; i++)
{
ll temp = n - a[i];
if (p.lower_bound(temp) == p.end())
{
ans[i] = (a[i] + *p.begin()) % n;
p.erase(p.begin());
}
else
{
temp = *(p.lower_bound(temp));
//cout << temp << endl;
ans[i] = (a[i] + temp) % n;
p.erase(p.lower_bound(temp));
//cout << n-temp << " "<<p.size()<<endl;
}
}
for (rg i = 1; i <= n; i++)
{
i == n ? cout << ans[i] : cout << ans[i] << " ";
}
return 0;
}
- C语言第五讲,语句 顺序循环选择.
- C语言第四讲,typedef 关键字,以及作用域
- C语言第三讲,基本数据类型
- 64位内核第二讲,进程保护之对象钩子
- x64内核HOOK技术之拦截进程.拦截线程.拦截模块
- Spring开启方法异步执行
- 64位内核第一讲,和32位内核的区别
- Maven精选系列--发布jar包到Nexus私库
- 《SpringMVC从入门到放肆》五、SpringMVC配置式开发(处理器适配器)
- 《SpringMVC从入门到放肆》四、SpringMVC配置式开发(处理器映射器)
- 什么是Spring Boot?
- 《SpringMVC从入门到放肆》三、DispatcherServlet的url-pattern配置详解
- 《SpringMVC从入门到放肆》二、SpringMVC的执行流程及默认配置
- 《SpringMVC从入门到放肆》一、概述
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Python爬虫-MongoDB
- Python爬虫-selenium
- 用Python识别图形验证码,实现自动登陆!
- 当Docker遇到Intellij IDEA,再次解放了生产力~
- 用Python爬取自主品牌汽车,看看国产汽车究竟长什么样?(上)
- 工具包 | 使用Python绘制Sci学术期刊配图
- 深入剖析AQS和CAS,看了都说好
- 用Python爬取自主品牌汽车,看看国产汽车究竟长什么样?(下)
- 读者问:小林怎么学操作系统和计算机网络呀?
- 用Python搭建一个简单的代理池
- 用Python模拟登陆GitHub并获取信息
- APUE学习手札 编写一个与3.12节中dup2功能相同的函数,要求不调用fcntl函数,并且要有正确的出错处理
- Python教程 | 最标准的地图调用方式(国家测绘局提供数据)
- Python数据可视化:Python大佬有哪些?
- 新手一看就懂的线程池