如题,CSP-S 备赛中,复习一下 STL 库的用法节省时间。
内容不会太详细到原理,只知道用法就好。
  向量(Vector)  介绍向量是 STL 中的一种动态数组,索引(下标)从 0 开始。 向量使用连续的内存块来存储元素,这使得它们在访问和迭代方面非常高效。 使用向量类型前,需要引入vector 头文件   操作使用以下代码创建存储type 类型变量,名为vec 的向量:
当然,可以进行更细致的初始化:
1 2 3 std::vector<int > v1 (10 )  ; std::vector<int > v2 (10 , 5 )  ;  std::vector<int > v3 = {1 , 2 , 3 , 4 , 5 }; 
而后,可以进行加入、插入、删除、清空、访问、获取元素数量等操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 struct  type  {     int  temp;     type (int  t) : temp (t) {} }; std::vector<type> vec;int  var;size_t  offset; vec.push_back (type (var));  vec.emplace_back (var);  vec.insert (vec.begin () + offset, type (var));  vec.pop_back ();  vec.erase (vec.begin () + offset);  vec.clear ();  vec[offset]  vec.size (); 
  用例  题目描述你被邀请参加一个图书仓库管理系统的编程挑战。系统需要处理一系列指令,对图书仓库进行操作。仓库开始时为空,你需要根据以下指令类型操作图书仓库:
A S 向仓库最后添加一本名为S 的图书。D 从仓库中移除最后一本图书(如果仓库非空), 如果仓库为空,则输出Warehouse is empty。C 清空仓库中所有图书。I X S 在仓库中的第X 个位置(从1 开始计数)插入一本名为S 的图书。如果X 大于当前图书总数,将图书添加到仓库末尾。Q 查询并返回当前仓库中图书的总数。P X 输出第X 个位置(从1 开始计数)的图书名称。如果位置X 超出范围,则输出Invalid Position。  输入描述第一行包含一个整数N(1≤N≤105 ),表示指令的数量。 接下来的N 行,每行包含一个指令,按照上述格式给出。
  输出描述对于每个查询指令(Q),输出当前仓库中图书的总数。 对于每个位置查询指令(P),输出该位置的图书名称或Invalid Position。
  样例输入1 2 3 4 5 6 7 8 9 10 11 10 D A Harry Potter A The Great Gatsby Q I 2 To Kill a Mockingbird Q D Q P 1 P 3
  样例输出1 2 3 4 5 6 Warehouse is empty 2 3 2 Harry Potter Invalid Position
  题解没什么难度的模拟,直接写就好了。
难点不在向量,而在输入与字符串分割。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 #include  <bits/stdc++.h>  using  namespace  std;int  main ()   {     int  command_count;     cin>>command_count;     cin.ignore ();     vector<string> books;     vector<string> log;     string command;     for (int  i = 0 ; i < command_count; i++) {         getline (cin, command);         char  action = command[0 ];         size_t  space_index, position;         string book_name;         switch (action) {             case  'A' :                 book_name = command.substr (2 );                 books.push_back (book_name);                 break ;             case  'D' :                 if (books.empty ()) log.push_back ("Warehouse is empty" ); 				else  books.pop_back ();                 break ;             case  'C' :                 books.clear ();                 break ;             case  'Q' :                 log.push_back (to_string (books.size ()));                 break ;             case  'P' :                 position = stoi (command.substr (2 ));                 if (position <= 0  || position > books.size ()) log.push_back ("Invalid Position" );                 else  log.push_back (books[position - 1 ]);                 break ;             case  'I' :                 space_index = command.find (' ' , 2 );                 position = stoi (command.substr (2 , space_index - 2 ));                 book_name = command.substr (space_index + 1 );                 if (position > books.size ()) books.push_back (book_name);                 else  books.insert (books.begin () + position - 1 , book_name);                 break ;             default :                 break ;         }     }     for (const  auto  entry : log) {         cout<<entry<<endl;     }     return  0 ; }
  队列(Queue)  介绍队列是一种先进先出(FIFO)的数据结构。 使用队列类型前,需要引入queue 头文件。   操作使用以下代码创建存储type 类型变量,名为q 的队列:
可以进行加入、移除、访问、获取元素数量等操作(注意没有清空,所有类型的队列都没有):
1 2 3 4 5 6 7 8 9 std::queue<int > q;int  var; q.push (var);  q.pop ();  q.front ();  q.back ();  q.empty ();  q.size (); 
  用例此前写过两篇关于队列实现的文章(C++ 数组实现队列 与C++ 链表实现队列 ),可以看看。
问题、题解可以参考其中的 “解决问题” 部分。
这里给出使用 STL 队列的题解:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include  <bits/stdc++.h>  using  namespace  std;int  main ()   {     queue<int > q;     int  n;     cin>>n;     for (int  i = 1 ;i <=n;i++) q.push (i);     for (int  i = 1 ;!q.empty ();i++) {         if (i%2  == 0 ) {             int  temp = q.front ();             q.pop ();             q.push (temp);         }         else  {             cout<<q.front ()<<" " ;             q.pop ();         }     }     return  0 ; }
  双端队列(Deque)  介绍双端队列(Deque)是一种可以在两端进行插入和删除操作的队列。 使用双端队列类型前,需要引入deque 头文件。   操作使用以下代码创建存储type 类型变量,名为dq 的双端队列:
同样,可以进行在两端加入、移除、访问、获取元素数量等操作:
1 2 3 4 5 6 7 8 9 10 11 std::deque<int > dq;int  var; dq.push_back (var);  dq.push_front (var);  dq.pop_back ();  dq.pop_front ();  dq.front ();  dq.back ();  dq.empty ();  dq.size (); 
  优先队列(Priority Queue)或堆(Heap)  介绍优先队列(Priority Queue)是一种每次取出具有最高优先级元素的数据结构,一般按照从大到小的顺序存储(即大根堆)。 使用优先队列类型前,需要引入queue 头文件。 更多内容可以看看这篇堆 
  操作使用以下代码创建存储type 类型变量,名为pq 的优先队列:
1 std::priority_queue<type> pq;
可以进行加入、移除、访问、获取元素数量等操作:
1 2 3 4 5 6 7 8 std::priority_queue<int > pq;int  var; pq.push (var);  pq.pop ();  pq.top ();  pq.empty ();  pq.size (); 
也可以优先级,如下:
1 2 3 #include  <functional>    std::priority_queue<int , std::vector<int >, std::greater<int >> pq_min_heap; 
对于自定义类型,有:
1 2 3 4 5 6 7 8 9 10 11 struct  type  {     int  value; };struct  compare  {     bool  operator () (const  type& a, const  type& b)   {         return  a.value > b.value;     } } std::priority_queue<type, std::vector<type>, compare> 
  用例可以查看这里 获取题目与题解,这里只给出使用优先队列的写法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #include  <bits/stdc++.h>  using  namespace  std;int  main ()   {     int  n;     cin>>n;     priority_queue<int , vector<int >, greater<int >> min_heap;     int  temp;     for (int  i=0 ;i<n;i++) {         cin>>temp;         min_heap.push (temp);     }     int  power = 0 ;     while (min_heap.size () > 1 ) {         int  quick1 = min_heap.top ();         min_heap.pop ();         int  quick2 = min_heap.top ();         min_heap.pop ();         int  combined = quick1 + quick2;         power += combined;         min_heap.push (combined);     }     cout<<power<<endl;     return  0 ; }
  键值对(Map)  介绍顾名思义,一个键与一个值一一对应,通过键快速查找值。 map 通过红黑树实现。使用键值对类型前,需要引入map 头文件。 对于自定义类型的键,需要重载<操作符(键值对自带排序)。   操作使用以下代码创建键类型为KeyType,值类型为ValueType,名为mp 的键值对:
1 std::map<KeyType, ValueType> mp;
可以进行插入、删除、访问、查找、获取元素数量等操作(由于键的唯一性,不支持修改操作,可以先删除再插入):
1 2 3 4 5 6 7 std::map<int , std::string> mp;  mp[1 ] = "one" ;  mp.erase (1 );  mp[1 ]  mp.find (1 );  mp.size (); 
  哈希表版本 / 不排序  介绍利用桶函数实现,相比键值对它不会排序,速度快一些。 使用上与键值对无区别(需引入unordered_map 头文件),但内存利用率不够高。 对于自定义类型的键,需要重载哈希函数。   操作使用以下代码创建键类型为KeyType,值类型为ValueType,名为ump 的不排序键值对:
1 std::unordered_map<KeyType, ValueType> ump;
对于自定义类型的键:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 struct  KeyType  {     int  id;     std::string name;     bool  operator ==(const  KeyType &other) const  {         return  id == other.id && name == other.name;     } };namespace  std {     template <>     struct  hash <KeyType> {         std::size_t  operator () (const  KeyType& k)  const   {             using  std::hash;             using  std::size_t ;             using  std::string;             return  ((hash <int >()(k.id)                      ^ (hash <string>()(k.name) << 1 )) >> 1 );          }     }; }
 其它的不变。
  集合(Set)  介绍集合是一种不包含重复元素的数据结构(集合的互斥性)。 使用集合类型前,需要引入set 头文件。 对于自定义类型,需要重载<操作符(集合自带排序)。   操作使用以下代码创建存储type 类型变量,名为s 的集合:
可以进行插入、删除、访问、查找、获取元素数量等操作(由于集合的互斥性,不支持修改操作,可以先删除再插入):
1 2 3 4 5 6 std::set<int > s; s.insert (1 );  s.erase (1 );  s.find (1 );  s.size (); 
  哈希表版本 / 不排序  介绍引用unordered_set 以使用。 同样,速度更快,内存利用率下降。 个人感觉这个更接近于数学意义上的集合(无序性)。 对于自定义类型,需要重载== 操作符与哈希函数。   操作使用以下代码创建存储type 类型变量,名为us 的不排序集合:
1 std::unordered_set<type> us;
对于自定义类型:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 struct  type  {     int  id;     std::string name;     bool  operator ==(const  type &other) const  {         return  id == other.id && name == other.name;     } };namespace  std {     template <>     struct  hash <type> {         std::size_t  operator () (const  type &myType)  const   {             return  std::hash <int >()(type.id) ^ std::hash <std::string>()(type.name);         }     }; }
 其它的不变。
  补充除了粗暴的重载,unordered_map 与unordered_set 都可以通过自定义的哈希函数进行构造。
参考以下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 struct  type  {     int  a;     std::string b;     bool  operator ==(const  MyStruct &other) const  {         return  a == other.a && b == other.b;     } };struct  TypeHash  {     std::size_t  operator () (const  type &s)  const   {         std::size_t  h1 = std::hash <int >()(s.a);         std::size_t  h2 = std::hash <std::string>()(s.b);         return  h1 ^ (h2 << 1 );      } }; std::unordered_map<type, ValueType, TypeHash> ump; std::unordered_set<type, TypeHash> us;
  题外话没什么可说的……What can I say?  马上升高二了。
最后一次 CSP 与 NOIP,加油!