简单常见的STL的学习
来源:互联网 发布:衣服淘宝店铺 编辑:程序博客网 时间:2024/05/16 02:24
[pre] STL 容器的分类:
标准STL序列容器:vector、string、deque和list。
标准STL关联容器:set、multiset、map和multimap。
非标准序列容器slist和rope。slist是一个单向链表,rope本质上是一“重型”string。
非标准的关联容器hash_set、hase_multiset、hash_map和hash_multimap。
(一)vector
vector 的好处就是它分配的是动态空间。
vector <int> v;
12_23
不vector 的好处远不止上述那样简单!
vector
类是以容器(Container) 模式为基准设计的,也就是说,基本上它有begin()
,end()
,size()
,max_size()
,empty()
以及swap()
这几个方法。
from wiki:
- 访问元素的方法
vec[i]
- 访问索引值为 i 的元素引用。 (索引值从零起算,故第一个元素是vec[0]。)vec.at(i)
- 访问索引值为 i 的元素的引用,以 at() 访问会做数组边界检查,如果访问越界将会抛出一个例外,这是与operator[]的唯一差异。vec.front()
- 回传 vector 第一个元素的引用。vec.back()
- 回传 vector 最尾元素的引用。
- 新增或移除元素的方法
vec.push_back()
- 新增元素至 vector 的尾端,必要时会进行存储器配置。vec.pop_back()
- 删除 vector 最尾端的元素。vec.insert()
- 插入一个或多个元素至 vector 内的任意位置。vec.erase()
- 删除 vector 中一个或多个元素。vec.clear()
- 清空所有元素。
- 获取长度/容量
vec.size()
- 获取 vector 目前持有的元素个数。vec.empty()
- 如果 vector 内部为空,则传回 true 值。vec.capacity()
- 获取 vector 目前可容纳的最大元素个数。这个方法与存储器的配置有关,它通常只会增加,不会因为元素被删减而随之减少。
- 重新配置/重置长度
vec.reserve()
- 如有必要,可改变 vector 的容量大小(配置更多的存储器)。在众多的 STL 实做,容量只能增加,不可以减少。vec.resize()
- 改变 vector 目前持有的元素个数。
- 迭代 (Iterator)
vec.begin()
- 回传一个Iterator,它指向 vector 第一个元素。vec.end()
- 回传一个Iterator,它指向 vector 最尾端元素的下一个位置(请注意:它不是最末元素)。vec.rbegin()
- 回传一个反向Iterator,它指向 vector 最尾端元素的。vec.rend()
- 回传一个Iterator,它指向 vector 的第一个元素。
vec.insert()
- 插入一个或多个元素至 vector 内的任意位置。这一行了吗? 它支持像rope一样在特定位置插入一个或多个元素。于是就可以用它来写平衡树的题了?
函数upper_bound()返回的在前闭后开区间查找的关键字的上界
bzoj 3224
用十几行水过不能再帅!
#include <iostream>#include <cstdio>#include <vector>using namespace std;vector <int> a;int main(){ int n; scanf("%d", &n); for(int i = 1; i <= n; i ++){ int la, x; scanf("%d%d", &la, &x); if(la == 1)a.insert(upper_bound(a.begin(), a.end(), x), x); if(la == 2)a.erase(lower_bound(a.begin(), a.end(), x)); if(la == 3)printf("%d\n", lower_bound(a.begin(), a.end(), x) - a.begin() + 1); if(la == 4)printf("%d\n", a[x - 1]); if(la == 5)printf("%d\n", *-- lower_bound(a.begin(), a.end(), x)); if(la == 6)printf("%d\n", *upper_bound(a.begin(), a.end(), x)); } return 0;}
常用函数总结:
upper_bound(a.begin(), a.end(), x);lower_bound(a.begin(), a.end(), x);a.insert(pos, x);a.erase(pos);a.push_back(x)
(二) set
set 做的事情是动态地维护一个排序, 支持 查找键值 为 K 的点和 删除 简直 为K 的点 (但不能 超找或删除第K大的点)(而且它所包含的元素的值是唯一的)
set<int> s1;
set<char, scmp> s2; 排序准则自定义为 scmp
begin() ,返回set容器的第一个元素
end() ,返回set容器的最后一个元素
clear() ,删除set容器中的所有的元素
empty() ,判断set容器是否为空
max_size() ,返回set容器可能包含的元素最大个数
size() ,返回当前set容器中的元素个数
erase(iterator) ,删除定位器iterator指向的值
erase(first,second),删除定位器first和second之间的值
erase(key_value),删除键值key_value的值
find() ,返回给定值值得定位器,如果没找到则返回end()。
insert(key_value); 将key_value插入到set中 ,返回值是pair<set<int>::iterator,bool>,bool标志着插入是否成功,而iterator代表插入的位置,若key_value已经在set中,则iterator表示的key_value在set中的位置。
inset(first,second);将定位器first到second之间的元素插入到set中,返回值是void.
lower_bound(key_value) ,返回第一个大于等于key_value的定位器
upper_bound(key_value),返回最后一个大于等于key_value的定位器
例:
bzoj 1208 宠物收养所
当时用splay 打怎么也得六七十行呢吧。
用set 一下子变成普及组难度。。
UserProblemResultMemoryTimeLanguageCode_LengthSubmit_Timeset版1208Accepted1408 kb264 msC++/Edit779 B2014-12-15 20:36:07splay版1208Accepted2524 kb240 msC++/Edit2013 B2014-12-02 14:30:44对比代码长度, 占用内存, 和时间, 觉得 set 的优势真的挺大的。
#include <iostream>#include <cstdio>#include <set>#define INF 1<<31 - 1#define mod 1000000using namespace std;int n, flag = -1, ans;set <int> d;int main(){ scanf("%d", &n); d.insert(-INF); d.insert(INF); for(int i = 1; i <= n; i ++){ int a, b; scanf("%d%d", &a, &b); if(a == flag || d.size() == 2)flag = a, d.insert(b); else{ int r = *d.lower_bound(b), l = *-- d.lower_bound(b); if(b - l <= r - b && l != -INF){ans += b - l; d.erase(l);} else {ans += r - b; d.erase(r);} ans %= mod; } } cout<<ans<<endl; return 0;}
(三), map
map 真的很常用, 学了不下五遍了。
map 就是一个一对一 的数据映射, 它存的是一个pair,
例:
hdu 1004
虽然这题本来就不难, 但是觉得这种STL题简直是在秀下线。
#include <iostream>#include <cstdio>#include <algorithm>#include <map>#define si string, int#define smap map <si>using namespace std;smap s;inline bool cmp(pair<si> a, pair<si> b){return a.second < b.second;}int main(){ int n; while(scanf("%d", &n) && n){ s.clear(); char ch[22]; for(int i = 1; i <= n; i ++)scanf("%s", ch), s[ch] ++; smap::iterator la = max_element(s.begin(), s.end(), cmp); cout<<la -> first<<endl; } return 0;}
(四) , rope
上面的表格已经可以很好的说明rope和string的差别了。
rope的特点就是维护一个串, 支持log n插入和删除制定位置的字符。
fhq实现的rope
bzoj 1507
splay写这题的时候。。本机测可过bzoj莫名RE
rope写得被吓傻。。
用rope的时候,注意要多加的是:
#include <ext/rope>
using namespace __gnu_cxx (这行要记得(虽然它是下划线开头的, 但是是声明空间所以可以用))。
#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <ext/rope>using namespace std;using namespace __gnu_cxx;char s[2500005], s1[22];int n, now, k;crope S;int main(){ scanf("%d", &n); while(n --){scanf("%s", s1); if(s1[0] == 'M')scanf("%d", &now); if(s1[0] == 'P')now --; if(s1[0] == 'N')now ++; if(s1[0] == 'I'){ scanf("%d", &k); getchar(); for(int i = 0; i < k; i ++)do{s[i] = getchar();}while(s[i] == '\n'); s[k] = 0; S.insert(now, s); } if(s1[0] == 'D')scanf("%d", &k), S.erase(now, k); if(s1[0] == 'G')scanf("%d", &k), S.copy(now, k, s), s[k] = 0, puts(s); } return 0;}
bzoj 1269
/************转自hzwer*********************/
由于rope的底层实现,insert,erase,get都是logn的
就是翻转不行,不是自己手写的打不了标记啊!!
怎么办?
答:同时维护一正一反两个rope……反转即交换两个子串……Orz……
区间循环位移?简单,拆成多个子串连起来就好了……
区间a变b b变c c变d …… z变a? 呃……维护26个rope?
区间和?滚蛋,那是线段树的活
区间kth?sorry,与数值有关的操作rope一概不支持……
函数功能push_back(x)在末尾添加xinsert(pos,x)在pos插入xerase(pos,x)从pos开始删除x个replace(pos,x)从pos开始换成xsubstr(pos,x)提取pos开始x个at(x)/[x]访问第x个元素/********************************************/
- 简单常见的STL的学习
- stl的常见函数
- 学习STL 做个简单的笔记
- STL 常见的注意问题
- C++ STL的常见用法
- STL 常见的注意问题
- [STL] string的常见用法
- C++ STL的常见用法
- STL的简单应用
- STL的简单算法
- 简单的常见错误
- C++STL学习(12)STL深入(1) 设计简单的空间配置器
- STL 的学习
- stl的学习
- effective STL的学习
- STL的学习
- 学习STL的笔记
- STL——常见的一些问题
- sublimetext乱码问题解决方案(mac和windows都适用)
- 16.Swift-ARC
- poj3414(bfs广度优先搜索)
- Linux查看ip的命令详解
- 工作周报023
- 简单常见的STL的学习
- Sharepoint2010 列表默认视图更新
- Java的方法绑定
- mac下得OpenGL开发环境
- const注意
- 柯南君:看大数据时代下的IT架构(6)消息队列之RabbitMQ--案例(Publish/Subscribe起航)
- 数据分布式插入
- python 字典入库(mysql)函数
- mktime 夏令时