清明节给大一的孩子们讲了点STL的应用,下了些功夫,搬到这里来供大家学习交流。
1.泛型程序设计简介与迭代器的介绍
2.常见的STL容器及其例题应用(UVA10474,UVA101,UVA10815,UVA156,UVA540,UVA136
HDU1027,CF501B,HDU1716,HDU4277)
3.相关练习和思路
1.泛型程序设计简介与迭代器的介绍
1.1 泛型程序设计简介
泛型程序设计,简单地说就是使用模板的程序设计法。将一些常用的数据结构(比如链表,数组,二叉树)和算法(比如排序,查找)写成模板,以后则不论数据结构里放的是什么对象,算法针对什么样的对象,则都不必重新实现数据结构,重新编写算法。
总而言之,不多赘述,有了STL,不必再从头写大多的标准数据结构和算法,并且可获得非常高的性能。
1.2迭代器
- 可遍历STL容器内全部或部分元素的对象
- 指出容器中的一个特定位置
- 所有容器都提供获得迭代器的函数
操作 |
效果 |
begin() |
返回一个迭代器,指向第一个元素 |
end() |
返回一个迭代器,指向最后一个元素之后 |
半开区间[beg, end)的好处:
1.为遍历元素时循环的结束时机提供了简单的判断依据(只要未到达end(),循环就可以继续)
2.不必对空区间采取特殊处理(空区间的begin()就等于end())
2.常见的STL容器及其例题应用
2.1Sort
例题1:UVA 10474 Where is the Marble
题目:题目意思就是给出两个数m和n下面输入m个数,再依次输入n个数,查找n个数在前面的m个数中是第几大
思路很简单,排序加查找(也可以二分优化)。
这里简述sort函数的用法
头文件:
格式:
sort(vect.begin(), vect.end());
sort(vect.begin(), vect.end(), less() );
第三个参数可以自定义,主要用于自定义类型的排序
我这里用哈希写的,O(N)
我这里用哈希写的,O(N)
/*********************************
日期:2015-04-05
作者:matrix68
题号: UVA 10474 - Where is the Marble?
总结:sort使用练习
Tricks:
**********************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
2.2Vector
2.2.1用法:
vector<类型> 名字;
例如 vector ve; vector ve;
自己定义的结构体什么的也可以往里塞
struct POINT
{
int x, y;
};
vector ve;
2.2.2基本操作
ve.push_back(const value_type &val);
作用是在数组后面增加一个元素。括号里填的是ve里装的东西
ve.clear();清空ve里的所有元素。
ve.empty();判断ve是否为空,如果是返回true,否则false
ve.size();返回ve的长度。注意这里返回的类型是unsigned int,如果ve是空的ve.size() - 1就会爆掉。使用的时候一定要小心(做TC的时候被坑了一次)
ve.pop_back() 删除数组里的最后一个元素。
2.2.3例题
例题2:UVA101 The Blocks Problem
题目:给你n个方块,有四种操作:
1.move a onto b,把a和b上面的方块都放回原来位置,然后把a放到b上面;
2.move a over b,把a上面的放回原处,然后把a放在b所在的方块堆的上面;
3.pile a onto b,把b上面的放回原来位置,然后把a和a上面的方块整体放到b上面;
4.pile a over b,把a和a上面的方块整体放到b所在堆的上面。
定义两个基本操作:
1.将a上面的还原init_place(a);
2.将a和上面的(可以没有上面的)放到b上面pile_a_to_b(a,b)。
那么上述的四组操作就变成下面了:
1.move a onto b,init_place(a);init_place(b);pile_a_to_b(a,b);
2.move a over b,init_place(a);pile_a_to_b(a,b);
3.pile a onto b,init_place(b);pile_a_to_b(a,b);
4.pile a over b,pile_a_to_b(a,b)。
/*********************************
日期:2015-04-05
作者:matrix68
题号: UVA101 - The Blocks Problem
总结:vector使用练习,大模拟
Tricks:check不可以在外面再去输出,否则为size=0的也会被输出
**********************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
2.3 Set
2.3.1用法:
set<类型> 名字;
例如 set se; set se;
自己定义的结构体什么的也可以往里塞
struct POINT
{
int x, y;
};
set se;
2.3.2基本操作对集合a中元素的有
插入元素:a.insert(1);
删除元素(如果存在):a.erase(1);
判断元素是否属于集合:if (a.find(1) != a.end()) ...
返回集合元素的个数:a.size()
将集合清为空集:a.clear()
2.3.3例题
例题3:UVA 10815 Andy's First Dictionary
题目:给出一串单词,把所有单词改小写去重按字典序输出。
思路:set可以解决去重和排序问题。
set中每个元素最多只出现一次
set中的元素已经从小到大排序好
如何通过迭代器从小到大遍历所有元素
for (set::iterator i = d.begin(); i != d.end(); i++)
cout << *i << endl;
/*********************************
日期:2015-04-05
作者:matrix68
题号: UVA 10815 - Andy's First Dictionary
总结:set使用练习
Tricks:
**********************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
2.4 Map
2.4.1用法:
map添加数据;
map maplive; //第一个是键值,第二个是值
1.maplive.insert(pair(102,"aclive"));
2. maplive[112]="April";//map中最简单最常用的插入添加!
map中查找数据:
第一种:用count 函数来判定关键字是否出现,其缺点是无法定位数据出现位置,
由于map 的特性,一对一的映射关系,就决定了count 函数的返回值只有两个,
要么是0,要么是1,出现的情况,当然是返回1 了
第二种:用find 函数来定位数据出现位置,它返回的一个迭代器,当数据出现时,它返回数据所在位置的迭代器,如果map 中没有要查找的数据,它返回的迭代器等于end 函数返回的迭代器
注意:
Map中的元素是自动按key升序排序,所以不能对map用sort函数
但可以用迭代器按序遍历(与set类似)
2.4.2例题
例题4:UVA 156 Ananagrams
题目:把每个单词全部转化成小写字母,对每个单词,看它的字母重排后得到的单词在所有输入的单词中是否出现过,若没有出现,就输出原单词。所有要输出的单词按字典序排列输出。
思路:构造小写化函数,set可以解决去重和排序问题,用map建立string与int的映射
void string stand_words(string s1);
注意要存储原单词!
ps:也可以用multimap建立string与string的多重映射,即原单词与现单词的映射,方便提取原单词操作
/*********************************
日期:2015-04-05
作者:matrix68
题号: UVA 156 - Ananagrams
总结:map+set+vector使用练习
Tricks:
**********************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/*********************************
日期:2015-04-05
作者:matrix68
题号: UVA 156 - Ananagrams
总结:multimap使用练习
Tricks:string利用构造函数拷贝
**********************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
2.5 Queue
2.5.1
用法
和vector一样。
queue qu;
queue qu;
我一般都用它在BFS的时候存点。
2.5.2 常用操作
qu.push(const value_type &val); 元素入队
qu.pop()元素出队
qu.front() 获得队首元素
qu.empty() 判断qu是否为空,是的话返回true
qu.size() 获得qu的大小。
2.5.3例题
例题5:UVA 540 - Team Queue
题目:题意:有t个团队的人在排队。每次来了一个新人之后,如果他有队友在排队,那么这个新人会插队到队友的身后。要求支持三种指令:ENQUEUE x; DEQUEUE(队首出队); STOP。模拟这个过程,输出出队顺序
思路:模拟题。每个队列在一个大队列排队
queue q, q2[maxt];
q为总的团队队列,q2为每个团队的队列
/*********************************
日期:2015-04-05
作者:matrix68
题号: UVA 540 - Team Queue
总结:queue使用练习
Tricks:可能重复入队出队
**********************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
2.6 priority_queue(优先队列):默认从大到小排列。
2.6.1用法
priority_queue pqu;
如果要装结构体的话,要重载结构体的小于号,或者自己写一个cmp函数。
struct cmp
{
operator bool ()(int x, int y)
{
return x > y; // x小的优先级高
}
};
priority_queue, cmp>q;//第二个参数为容器类型。第三个参数为比较函数。
priority_queue, less> pq1; // 使用递减less函数对象排序
priority_queue, greater> pq2; // 使用递增greater函数对象排序
常用操作
push(),top(),pop(),empty();
2.6.2 例题
例题6:UVA 136 Ugly Number
题目:把只包含因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含因子7。习惯上我们把1当做是第一个丑数。求出第n个丑数。
思路:利用优先队列
//最后不要挨到一起,默认为位运算
priority_queue,greater >pq;
注意用long long!
/*********************************
日期:2015-04-05
作者:matrix68
题号: UVA 136 - Ugly Numbers
总结:优先队列使用练习
Tricks:
**********************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
也可以用set直接判重输出,这是我的写法:
/*********************************
日期:2015-04-05
作者:matrix68
题号: UVA 136 - Ugly Numbers
总结:set使用练习
Tricks:
**********************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
2.7 next_permutation(全排列):要包含头文件
2.7.1用法
2.7.2 例题
例题7:HDU 1027 Ignatius and the Princess II
题目:求N个数全排列,顺着数第M个
思路:利用next_permutation
while(m--)
{
next_permutation(num,num+n);
}
/*********************************
日期:2015-04-05
作者:matrix68
题号: HDU 1027 - Ignatius and the Princess II
总结:next_permutation使用练习
Tricks:
**********************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
例题9:HDU 1716 排列2
思路同理
注意输出格式易PE:每行末尾无0,最后一组数据末尾没有回车!
/*********************************
日期:2015-04-03
作者:
题号: HDU 1716 - 排列2
总结:next_permutation的使用
Tricks:0开始的忽略
重复的不计
写吐了,while里面乱搞的。。。出题不善,大家跳过这个题吧
**********************************/
#include
#include
#include
#include
#include
#include
#include
#include
3.相关练习和思路
3.1
例题8:Codeforces 501B - Misha and Changing Handles
题目:有一些人改名字,输出每个人的原名和改了之后的名字.
思路:用map记录每个人换过的名字,用set记录是不是一个新的人,如果是的话就放到数组里。
/*********************************
日期:2015-04-05
作者:matrix68
题号: Codefores 501B - Misha and Changing Handles
总结:map使用练习
Tricks:建立新名字到旧名字的映射,把所有新名字放在set里排重。
**********************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
3.2
例题10:HDU 4277 - USACO ORZ
题目:给定一些一定长度的线段,要求全部利用这些线段能拼成多少种三角形(如果两个三角形至少有一条边长度不等那么二者视为两种)
思路:DFS,对于所有满足情况的三角形加入set中,这样就去重了,最后set的大小就是答案
set里面可以存两种:
自定义struct Past但必须重载<
LL构造每个三角形的唯一值
/*********************************
日期:2015-04-03
作者:matrix68
题号: HDU 4277 - USACO ORZ
总结:DFS+set
Tricks:注意用long long
**********************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include