三天STL与pbds(平板电视)

19.02.11 ~ 19.02.13
hjmmm要专攻STL辣
先列一下大纲?

  • 第一天:各种基础容器
  • 第二天:实现厉害一点的结构(半咕咕)
  • 第三天:非变异算法和变异算法

那么我们就开始吧!

Day1

【各种基础容器】
还是先列一下小目录

  • vector
  • deque
  • list
  • queue & stack
  • priority_queue
  • biset
  • 集合 set
  • 映射 map
分类
种类名称
序列性容器 (可以用链表模拟的那种)vector, deque, list
关联性容器 (可以用平衡树模拟的那种)set, map, multiset, multimap
容器适配器(可以用数组模拟的那种)stack, queue

基本每个容器都会有的又

比较常用的函数
函数名函数类型意义
.empty()bool没有元素返回true
.size()int元素个数
.max_size()int最大元素个数
=operator将一个容器赋给另一个容器
swapvoid交换两个容器的元素
.begin()iterator返回第一个元素
.end()iterator返回最后一个元素后面的元素
.erase(xxx)void清除一个元素或几个元素
.clear()void清空所有元素
头文件要求

基本上都是 #include <容器名>

好啦现在分别突破!

vector & deque & list

共有的函数

小声:我一直不知道insert函数返回的那个迭代器是什么。。
知道的大佬麻烦在评论指导一下qvq感恩不尽
另外我没写构造函数因为蒟蒻一般不用。。

函数名函数类型意义
.insert(iterator it, const T& x)iterator在it所指那个元素前加一个x元素
.insert(iterator it, int n, const T& x)void在it所指那个元素前加n个x元素
.insert(iterator it, const_iterator first, const_iterator end)void在it所指那个元素前加入另一个同类型容器[first, last)之间的数据
.push_back(const T& x)void尾部增加元素x
.push_front(const T& x) (只有deque,list可以用)void首部增加元素x
.erase(iterator it)iterator删除it所指元素
.erase(iterator first, iterator last)iterator删除[first, last)之间的元素
.pop_back()void容器不为空时,删除最后一个元素
.pop_front() (只有deque,list可以用)void容器不为空时,删除第一个元素
.front()reference(引用)首元素引用
.back()reference尾元素引用
.assign(int n, const T& x)void设置容器大小为n每个元素为x
.assign(const_iterator first, const_iterator last)void设置容器有且只有[first, last)中的元素

deque,vector貌似没有什么别的常用操作了。。
list还有好多、

函数名函数类型意义
.remove(const T& x)void删除元素值等于x的元素
.sort()void排序(默认升序)
.unique()void去重
.reverse()void反转顺序
.splice(iterator it, list& x)void将x中所有元素移入当前list的it元素前
.splice(iterator it, list& x, iterator first)void将x中[first, end)元素移入当前list的it元素前
.splice(iterator it, list& x, iterator first, iterator last)void将x中[first, last)元素移入当前list的it元素前
.merge(list& x)void将x与当前list合并(不同于splice的是, 两序列若各自升序,合并完还是升序)

需要注意的是

  • 对任何位置的插入和删除 list永远是常数时间
  • vector容量翻倍开,容易炸哦
  • vector随机位置插入删除元素比较慢
  • deque随机位置操作是线性时间
  • list随机位置插入较快 但不支持随机访问

stack & queue & priority_queue

这个大家都跟熟悉啦~

共有的函数
函数名函数类型意义
.push(const T& x)void插入元素(队尾or栈顶)
.pop()void删除元素(队尾or栈顶)

各自的

  • 队首.front()
  • 队尾.back()
  • 栈顶或优先队列堆顶 .top()
    返回值都是reference哦

bitset ?

哦天, 卡常大神器, 我爱了

它是一个二进制容器,可以看作一个巨大的二进制数
可以拿来做状压

它还有空间优化,每个元素一般只占1 bit,这是什么概念?
相当于一个char元素所占空间的八分之一

这篇博客我看了七八遍 orz胡小兔 安利
所有的位运算可以对bitset直接操作

领养一只bitset:
bitset<位数> 名字;

bitset的常用函数
  • 大小
    foo.size()返回大小(位数)
  • 数1
    foo.count()返回1的个数
    foo.any()返回是否有1
    foo.none()返回是否没有1
  • 赋值
    foo.set() 全都变成1
    foo.set(p) 将第p + 1位变成1
    foo.reset()全都变成0
    foo.reset(p) 将第p + 1位变成0
    foo.set(p, x)将第p + 1位变成x
  • 取反
    foo.flip() 全都取反
    foo.flip(p) 将第p + 1位取反
  • 转换
    foo.to_ulong() 返回它转换为unsigned long的结果,如果超出范围则报错
    foo.to_ullong() 返回它转换为unsigned long long的结果,如果超出范围则报错
    foo.to_string() 返回它转换为string的结果

set & map & 它们的multi

set是集合(元素类型为Key), map是映射(元素类型为pair<Key, Value>), multi就是允许重复

共有的函数

Key指key的类型, Value指value的类型

函数名函数类型意义
.insert(const T& x)iterator或者pair<iterator, bool>插入x元素
.insert(iterator it, const T& x)iterator在it所指处插入x元素
.insert(const_iterator first, const_iterator end)void插入另一个同类型容器[first, last)之间的数据
.erase(const Key& key)size_type(这是啥?)删除元素值(键值)等于key的元素(multiset和multimap删除的可能不止一个!)
.erase(iterator it)iterator删除it所指元素
.erase(iterator first, iterator last)iterator删除[first, last)之间的元素
.lower_bound(const Key& key)const_iterator返回大于等于key的最小元素的指针,没有则返回end()
.upper_bound(const Key& key)const_iterator返回大于key的最小元素的指针,没有则返回end()
.count(const Key& key)int返回元素值(键值)等于key的元素个数
.equal_range(const Key& key)pair<const_iterator, const_iterator>返回元素中等于key的迭代器指针[first, last)
.find(const Key& key)const_iterator返回元素中等于key的迭代器指针

okk 今天就到这里吧 每天update哦~

最后安利一个比STL还STL noip还可以用!的东西

Day2

  • vector代替平衡树

    luogu3369普通平衡树的代码
    亲测在这里插入图片描述
    加上头文件一共26行

#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector> 
using namespace std;
int n;
vector<int> tree;
int main() {
 int x, opt;
 scanf("%d", &n);
 for(int i = 1; i <= n; ++i){
  scanf("%d%d", &opt, &x);
  int pos = lower_bound(tree.begin(), tree.end(), x) - tree.begin();
  switch(opt){
   case 1: tree.insert(tree.begin() + pos, x); break;
   case 2: tree.erase(tree.begin() + pos, tree.begin() + pos + 1); break;
   case 3: printf("%d\n", pos + 1); break;
   case 4: printf("%d\n", tree[x - 1]); break;//注意这里是x-1哦 
   case 5: printf("%d\n", tree[pos - 1]); break;
   case 6: printf("%d\n", *upper_bound(tree.begin(), tree.end(), x)); break;
  }
 }
 return 0;
}

但是有这么个小问题
这些容器 好像都维护不了区间和欸。。

又切了几道题 就算Day2吧

pbds的平衡树

这里仅陈列pbds平衡树常用用法
参考博客

包含:ext/pb_ds/assoc_container.hpp和ext/pb_ds/tree_policy.hpp
声明:__gnu_pbds::tree

typename Key , typename Mapped ,
typename Cmp_Fn = std :: less <Key >,
typename Tag = rb_tree_tag ,
template <
    typename Const_Node_Iterator ,
    typename Node_Iterator ,
    typename Cmp_Fn_ , typename Allocator_ >
class Node_Update = null_tree_node_update ,
typename Allocator = std :: allocator <char > >

class tree ;

注:如果有第二优先排序的话,用pair(先拍first)

过于常见:

  • .begin()
  • .end()
  • .size()
  • .empty()
  • .clear()

常见:

  • .begin() 最小值
  • .end() 最大值后一位
  • .find_by_order(val)返回迭代器 第val个数
  • .order_of_key(val) 返回值 比他小的数有多少个
  • .find(const Key)
  • .lower_bound(const Key) 返回迭代器
  • .upper_bound(const Key)返回迭代器
  • .erase(iterator)
  • .erase(const Key)
  • .insert(const pair<> )
  • .operator[]
  • void join(tree &other) 把other中所有元素移动到*this上(值域不能相交,否则抛出异常。
  • void split(const_key_reference r_key, tree &other) 清空other,然后把*this中所有大于r_key的元素移动到other。
  • get_l_child和get_r_child 左右儿子

自定义update:

template < class Node_CItr , class Node_Itr ,
    class Cmp_Fn , class _Alloc  >
struct my_node_update {
    virtual Node_CItr node_begin () const = 0;
    virtual Node_CItr node_end () const = 0;
    typedef int metadata_type ;
    inline void operator ()( Node_Itr it , Node_CItr end_it ){
        Node_Itr l = it. get_l_child (), r = it. get_r_child ();
        int left = 0, right = 0;
        if(l != end_it ) left = l. get_metadata ();
        if(r != end_it ) right = r. get_metadata ();
        const_cast < metadata_type &>( it. get_metadata ())
            = left + right + (* it)-> second ;
    }
    inline int prefix_sum (int x) {
        int ans = 0;
        Node_CItr it = node_begin ();
        while (it != node_end ()) {
            Node_CItr l = it. get_l_child (), r = it. get_r_child ();
            if( Cmp_Fn ()(x, (* it)-> first )) it = l;
            else {
                ans += (* it)-> second ;
                if(l != node_end ()) ans += l. get_metadata ();
                it = r;
            }
        }
        return ans;
    }
    inline int interval_sum (int l, int r){
        return prefix_sum (r) - prefix_sum (l - 1);
    }
}
int main() {
    tree <int , int , std :: less <int >, rb_tree_tag , my_node_update > T;
    T [2] = 100; T [3] = 1000; T [4] = 10000;
    printf ("%d\n", T. interval_sum (3, 4));
    printf ("%d\n", T. prefix_sum (3));
} 

Day3

非变异算法

分为循环,查询,计数,比较四类
复杂度是线性的,感觉用不太上,简单看看就好啦。。
转自
在这里插入图片描述

变异算法

转自
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值