(C/C++)STL函数(3)二分算法题以及二分模板 和(蓝桥杯)递推与递归题目及解法(ACwing)

简介: (C/C++)STL函数(3)二分算法题以及二分模板 和(蓝桥杯)递推与递归题目及解法(ACwing)

一、STL函数


1、#include <deque>

双端队列deque是一个支持在两端高效插入或删除元素的连续线性存储空间。它就像是vector和queue的结合。与vector相比,deque在头部增删元素仅需要 O(1)O(1) 的时间;与queue相比,deque像数组一样支持随机访问。

[]              // 随机访问
begin/end       // 返回deque的头/尾迭代器
front/back      // 队头/队尾元素
push_back       // 从队尾入队
push_front      // 从队头入队
pop_back        // 从队尾出队
pop_front       // 从队头出队
clear           // 清空队列


2.1、 #include <set>


头文件set主要包括set和multiset两个容器,分别是“有序集合”和“有序多重集合”,即前者的元素不能重复,而后者可以包含若干个相等的元素。set和multiset的内部实现是一棵红黑树,它们支持的函数基本相同。


2.2 size/empty/clear


与vector类似


2.3 迭代器


set和multiset的迭代器称为“双向访问迭代器”,不支持“随机访问”,支持星号*解除引用,仅支持++和--两个与算术相关的操作。


设it是一个迭代器,例如set<int>::iterator it;


若把it ++,则it会指向“下一个”元素。这里的“下一个”元素是指在元素从小到大排序的结果中,排在it下一名的元素。同理,若把it --,则it将会指向排在“上一个”的元素。


2.4 begin/end


返回集合的首、尾迭代器,时间复杂度均为 O(1)O(1)。


s.begin()是指向集合中最小元素的迭代器。


s.end()是指向集合中最大元素的下一个位置的迭代器。换言之,就像vector一样,是一个“前闭后开”的形式。因此-- s.end()是指向集合中最大元素的迭代器。


2.5 insert


s.insert(x)把一个元素x插入到集合s中,时间复杂度为 O(logn)O(logn)。


在set中,若元素已存在,则不会重复插入该元素,对集合的状态无影响。


2.6 find


s.find(x)在集合s中查找等于x的元素,并返回指向该元素的迭代器。若不存在,则返回s.end()。时间复杂度为 O(logn)O(logn)。


2.7 lower_bound/upper_bound


这两个函数的用法与find类似,但查找的条件略有不同,时间复杂度为 O(logn)O(logn)。


s.lower_bound(x)查找大于等于x的元素中最小的一个,并返回指向该元素的迭代器。


s.upper_bound(x)查找大于x的元素中最小的一个,并返回指向该元素的迭代器。


2.8 erase


设it是一个迭代器,s.erase(it)从s中删除迭代器it指向的元素,时间复杂度为 O(logn)O(logn)。


设x是一个元素,s.erase(x)从s中删除所有等于x的元素,时间复杂度为 O(k+logn)O(k+logn),其中 kk 是被删除的元素个数。


2.9 count


s.count(x)返回集合s中等于x的元素个数,时间复杂度为 O(k+logn)O(k+logn),其中 kk 为元素x的个数。(ACWing)


#include <iostream>
#include <set>
using namespace std;
int main ()
{
    set <int> a;// 元素不能重复
    multiset <int> b; // 元素可以重复
    struct Rec
    {
        int x, y;
        bool operator <(const Rec& t) const//重载小于号
        {
            return x < t.x;
        }
        set <Rec> c;//set定义一个结构体
    }
    set <int>::iterator it = a.begin();//定义一个迭代器
    it ++;//有序数对中加加
    it--;
    a.end();//表示最后一个元素的后一个数
    a.insert(x);
    if(a.find(x) == a.end()); //判断x在a中是否存在。
    a.low_bound(x);//找到大于等于x的最小的元素的迭代器
    a.upper_bound(x);//查找大于x的元素中最小的一个
    a.erase(x);//从a中删除迭代器x指代的元素
    a.count(x);
    return 0;
}


二、二分算法(数的精度


数的范围


给定一个按照升序排列的长度为 nn 的整数数组,以及 qq 个查询。


对于每个查询,返回一个元素 kk 的起始位置和终止位置(位置从 00 开始计数)。


如果数组中不存在该元素,则返回 -1 -1。


输入格式


第一行包含整数 nn 和 qq,表示数组长度和询问个数。


第二行包含 nn 个整数(均在 1∼100001∼10000 范围内),表示完整数组。


接下来 qq 行,每行包含一个整数 kk,表示一个询问元素。


输出格式


共 qq 行,每行包含两个整数,表示所求元素的起始位置和终止位置。


如果数组中不存在该元素,则返回 -1 -1。


数据范围


1≤n≤1000001≤n≤100000

1≤q≤100001≤q≤10000

1≤k≤100001≤k≤10000


输入样例:

6 3
1 2 2 3 3 4
3
4
5

输出样例:

3 4
5 5
-1 -1
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 100010;
int n, m;//n是数组长度,m表示查询次数
int q[N];
int main ()
{
    cin >> n >> m;
    for(int i = 0; i < n; i++) cin >> q[i];
    for(int i = 0; i < m; i++)
    {
        int x;
        cin >> x;
        int l = 0, r = n - 1;//定义左右两端点
        while(l < r)//递归求左端点
        {
            int mid = l + r >> 1;//l + r 除以2
            if(q[mid] >= x) r = mid;//说明q[mid]在答案右边此时mid的值赋给右边界
            else l = mid + 1;//否则q[mid]在答案左边此时mid+1的值赋给左边界
        }
        if(q[r] == x)
        {
            cout << r << ' ';//如果q[r] == x说明找到了起始的左边界并且输出
            r = n - 1;
            while(l < r)//递归求右端点
            {
                int mid = r + l + 1 >> 1;//mid 要加一是为了防止死循环
                if(q[mid] <= x) l = mid;//说明q[mid]在答案左边此时mid的值赋给左边界
                else r = mid - 1;//否则q[mid]在答案右边此时mid-1的值赋给右边界
            }
            cout << l << endl;
        }
        else cout << "-1 -1" << endl;
    }
    return 0;
}

三、(蓝桥杯)递推与递归题目及解法(ACwing)


1、递归实现指数型枚举


从 1∼n1∼n 这 nn 个整数中随机选取任意多个,输出所有可能的选择方案。


输入格式


输入一个整数 nn。


输出格式


每行输出一种方案。


同一行内的数必须升序排列,相邻两个数用恰好 11 个空格隔开。


对于没有选任何数的方案,输出空行。


本题有自定义校验器(SPJ),各行(不同方案)之间的顺序任意。


数据范围


1≤n≤151≤n≤15


输入样例:

3

输出样例:

3
2
2 3
1
1 3
1 2
1 2 3
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 20;//数组开大些
int st[N];//表示每个位置的当前状态,0表示还没考虑,1表示选他,2表示不选
int n;
void dfs(int u)
{
    if (u > n) //从1 开始,当 u > n 时表示已经到边界了
    {
        for(int i = 1; i <= n; i++)
        if(st[i] == 1)
            printf("%d ", i);
            printf("\n");
        return;
    }
    st[u] = 2;
    dfs(u + 1); //第一个分支,不选
    st[u] = 0;//恢复现场
    st[u] = 1;
    dfs(u + 1);//第二个分支,选
    st[u] = 0;
}
int main ()
{
    cin >> n;
    dfs(1);//从0位到n-1 位
    return 0;
}

2、递归实现排列型枚举


把 1∼n1∼n 这 nn 个整数排成一行后随机打乱顺序,输出所有可能的次序。


输入格式


一个整数 nn。


输出格式


按照从小到大的顺序输出所有方案,每行 11 个。


首先,同一行相邻两个数用一个空格隔开。


其次,对于两个不同的行,对应下标的数一一比较,字典序较小的排在前面。


数据范围


1≤n≤91≤n≤9


输入样例:

3

输出样例:

1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1

闫学灿老师画的递归搜索树


image.png

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 10; 
int n;
int st[N];//0表示还没放数,1到n表示放的数
bool used[N];
void dfs(int u)
{
    if(u > n)
    {
        for(int i = 1; i <= n; i++) printf("%d ", st[i]);
        puts("");
        return;
    }
    //依次枚举每个分支,即当前位置可以填哪些数
    for(int i = 1; i <= n; i++)
    if(!used[i])
    {
        st[u] = i;
        used[i] = true;
        dfs(u + 1);
        //恢复现场
        st[u] = 0;
        used[i] = false;
    }
}
int main ()
{
    cin >> n;
    dfs(1);
    return 0;
}
相关文章
|
3月前
|
编译器 C++ 容器
【c++丨STL】基于红黑树模拟实现set和map(附源码)
本文基于红黑树的实现,模拟了STL中的`set`和`map`容器。通过封装同一棵红黑树并进行适配修改,实现了两种容器的功能。主要步骤包括:1) 修改红黑树节点结构以支持不同数据类型;2) 使用仿函数适配键值比较逻辑;3) 实现双向迭代器支持遍历操作;4) 封装`insert`、`find`等接口,并为`map`实现`operator[]`。最终,通过测试代码验证了功能的正确性。此实现减少了代码冗余,展示了模板与仿函数的强大灵活性。
103 2
|
3月前
|
存储 算法 C++
【c++丨STL】map/multimap的使用
本文详细介绍了STL关联式容器中的`map`和`multimap`的使用方法。`map`基于红黑树实现,内部元素按键自动升序排列,存储键值对,支持通过键访问或修改值;而`multimap`允许存在重复键。文章从构造函数、迭代器、容量接口、元素访问接口、增删操作到其他操作接口全面解析了`map`的功能,并通过实例演示了如何用`map`统计字符串数组中各元素的出现次数。最后对比了`map`与`set`的区别,强调了`map`在处理键值关系时的优势。
210 73
|
19天前
|
人工智能 机器人 编译器
c++模板初阶----函数模板与类模板
class 类模板名private://类内成员声明class Apublic:A(T val):a(val){}private:T a;return 0;运行结果:注意:类模板中的成员函数若是放在类外定义时,需要加模板参数列表。return 0;
|
3月前
|
存储 算法 C++
【c++丨STL】set/multiset的使用
本文深入解析了STL中的`set`和`multiset`容器,二者均为关联式容器,底层基于红黑树实现。`set`支持唯一性元素存储并自动排序,适用于高效查找场景;`multiset`允许重复元素。两者均具备O(logN)的插入、删除与查找复杂度。文章详细介绍了构造函数、迭代器、容量接口、增删操作(如`insert`、`erase`)、查找统计(如`find`、`count`)及`multiset`特有的区间操作(如`lower_bound`、`upper_bound`、`equal_range`)。最后预告了`map`容器的学习,其作为键值对存储的关联式容器,同样基于红黑树,具有高效操作特性。
140 3
|
4月前
|
存储 缓存 C++
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
C++ 标准模板库(STL)提供了一组功能强大的容器类,用于存储和操作数据集合。不同的容器具有独特的特性和应用场景,因此选择合适的容器对于程序的性能和代码的可读性至关重要。对于刚接触 C++ 的开发者来说,了解这些容器的基础知识以及它们的特点是迈向高效编程的重要一步。本文将详细介绍 C++ 常用的容器,包括序列容器(`std::vector`、`std::array`、`std::list`、`std::deque`)、关联容器(`std::set`、`std::map`)和无序容器(`std::unordered_set`、`std::unordered_map`),全面解析它们的特点、用法
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
|
3月前
|
安全 C++
【c++】继承(继承的定义格式、赋值兼容转换、多继承、派生类默认成员函数规则、继承与友元、继承与静态成员)
本文深入探讨了C++中的继承机制,作为面向对象编程(OOP)的核心特性之一。继承通过允许派生类扩展基类的属性和方法,极大促进了代码复用,增强了代码的可维护性和可扩展性。文章详细介绍了继承的基本概念、定义格式、继承方式(public、protected、private)、赋值兼容转换、作用域问题、默认成员函数规则、继承与友元、静态成员、多继承及菱形继承问题,并对比了继承与组合的优缺点。最后总结指出,虽然继承提高了代码灵活性和复用率,但也带来了耦合度高的问题,建议在“has-a”和“is-a”关系同时存在时优先使用组合。
217 6
|
4月前
|
存储 算法 C++
【c++丨STL】priority_queue(优先级队列)的使用与模拟实现
本文介绍了STL中的容器适配器`priority_queue`(优先级队列)。`priority_queue`根据严格的弱排序标准设计,确保其第一个元素始终是最大元素。它底层使用堆结构实现,支持大堆和小堆,默认为大堆。常用操作包括构造函数、`empty`、`size`、`top`、`push`、`pop`和`swap`等。我们还模拟实现了`priority_queue`,通过仿函数控制堆的类型,并调用封装容器的接口实现功能。最后,感谢大家的支持与关注。
190 1
|
4月前
|
存储 算法 C++
深入浅出 C++ STL:解锁高效编程的秘密武器
C++ 标准模板库(STL)是现代 C++ 的核心部分之一,为开发者提供了丰富的预定义数据结构和算法,极大地提升了编程效率和代码的可读性。理解和掌握 STL 对于 C++ 开发者来说至关重要。以下是对 STL 的详细介绍,涵盖其基础知识、发展历史、核心组件、重要性和学习方法。
|
22天前
|
机器学习/深度学习 算法 数据安全/隐私保护
基于PSO粒子群优化TCN-LSTM时间卷积神经网络时间序列预测算法matlab仿真
本内容展示了一种基于粒子群优化(PSO)与时间卷积神经网络(TCN)的时间序列预测方法。通过 MATLAB2022a 实现,完整程序运行无水印,核心代码附详细中文注释及操作视频。算法利用 PSO 优化 TCN 的超参数(如卷积核大小、层数等),提升非线性时间序列预测性能。TCN 结构包含因果卷积层与残差连接,结合 LSTM 构建混合模型,经多次迭代选择最优超参数,最终实现更准确可靠的预测效果,适用于金融、气象等领域。
|
18天前
|
算法 数据安全/隐私保护
基于Logistic-Map混沌序列的数字信息加解密算法matlab仿真,支持对文字,灰度图,彩色图,语音进行加解密
本项目实现了一种基于Logistic Map混沌序列的数字信息加解密算法,使用MATLAB2022A开发并包含GUI操作界面。支持对文字、灰度图像、彩色图像和语音信号进行加密与解密处理。核心程序通过调整Logistic Map的参数生成伪随机密钥序列,确保加密的安全性。混沌系统的不可预测性和对初值的敏感依赖性是该算法的核心优势。示例展示了彩色图像、灰度图像、语音信号及文字信息的加解密效果,运行结果清晰准确,且完整程序输出无水印。
基于Logistic-Map混沌序列的数字信息加解密算法matlab仿真,支持对文字,灰度图,彩色图,语音进行加解密