set
set就是集合。STL的set用二叉搜索树实现,集合中每个元素只出现一次,并且是排好序的。访问元素的时间复杂度是O()。
set和map在竞赛中应用广泛,特别是需要使用二叉搜索树处理数据的题目,用set和map可以极大地简化代码。
set的有关操作
set<Type> a; //定义Type类型的set,a
a.insert(item); //把item放入set
a.erase(item); //删除元素item
a.clear(); //清空set
a.empty(); //判断是否为空
a.size(); //返回元素个数
a.find(k); //返回一个迭代器,指向键值k
a.lower_bound(k); //返回一个迭代器,指向键值不小于k的第一个元素
a.upper_bound(k); //返回一个迭代器,指向键值大于k的第一个元素
例题(hdu 2094):
有一群人,打乒乓球比赛,两两捉对撕杀,每两个人之间最多打一场比赛。
球赛的规则如下:
如果A打败了B,B又打败了C,而A与C之间没有进行过比赛,那么就认定,A一定能打败C。
如果A打败了B,B又打败了C,而且,C又打败了A,那么A、B、C三者都不可能成为冠军。
根据这个规则,无需循环较量,或许就能确定冠军。你的任务就是面对一群比赛选手,在经过了若干场撕杀之后,确定是否已经实际上产生了冠军。
Input
输入含有一些选手群,每群选手都以一个整数n(n<1000)开头,后跟n对选手的比赛结果,比赛结果以一对选手名字(中间隔一空格)表示,前者战胜后者。如果n为0,则表示输入结束。
Output
对于每个选手群,若你判断出产生了冠军,则在一行中输出“Yes”,否则在一行中输出“No”。
Sample Input
3
Alice Bob
Smith John
Alice Smith
5
a c
c d
d e
b e
a d
0
Sample Output
Yes
No
思路:定义两个集合A和B,把所有人放入集合A,把失败的人放入集合B,若A-B=1,则输出YES;
代码如下:
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
while(cin>>n){
if(n==0) break;
string s1,s2;
set<string>a,b; //定义两个集合a,b
for(int i=1;i<=n;i++){
cin>>s1>>s2;
a.insert(s1); //所有参赛人员放入a
a.insert(s2);
b.insert(s2); //输的人放入b
}
if(a.size()-b.size()==1) cout<<"Yes"<<endl; //判断条件
else cout<<"No"<<endl;
}
return 0;
}
map
现在有一个很常见的问题:有n个学生,每个人都有自己的名字name和学号id,现在给定一个学生的 name,要求查找他的id;
简单的做法是定义string name[n]和int id[n](可以放在一个结构体中)存储信息,然后在name[]中查找这个学生,然后输出他的id。这样做的缺点就是需要搜索所有的name[],复杂度是O(n),效率未免太低;
而利用STL中的map容器可以快速地实现这个查找,复杂度是O()。
map是关联容器,它实现从键(Key)到值(Value)的映射。map效率高的原因是它用平衡二叉搜索树来存储和访问;
map的具体操作如下
(1)定义:map<string,int> student,存储学生的name和id;
(2)赋值:例如student["Tom"]=15。这里把”Tom"当成普通数组的下表来使用;
(3)查找:在查找学号的时候,可以直接用student["Tom"]表示他的id,不用再去搜索所有的姓名;
例题(hdu 2648):
Problem Description
Every girl likes shopping,so does dandelion.Now she finds the shop is increasing the price every day because the Spring Festival is coming .She is fond of a shop which is called "memory". Now she wants to know the rank of this shop's price after the change of everyday.
Input
One line contians a number n ( n<=10000),stands for the number of shops.
Then n lines ,each line contains a string (the length is short than 31 and only contains lowercase letters and capital letters.)stands for the name of the shop.
Then a line contians a number m (1<=m<=50),stands for the days .
Then m parts , every parts contians n lines , each line contians a number s and a string p ,stands for this day ,the shop p 's price has increased s.
Output
Contains m lines ,In the ith line print a number of the shop "memory" 's rank after the ith day. We define the rank as :If there are t shops' price is higher than the "memory" , than its rank is t+1.
Sample Input
3
memory
kfc
wind
2
49 memory
49 kfc
48 wind
80 kfc
85 wind
83 memory
Sample Output
1
2
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
while(cin>>n){
int m;
string s;
map<string,int> shop; //定义map
for(int i=1;i<=n;i++)
cin>>s; //第一次输入名称不用管它
cin>>m; //天数
while(m--){ //每天进行一次模拟
int t; //涨幅
string c; //名称
for(int i=1;i<=n;i++){
cin>>t>>c;
shop[c]+=t; //直接进行运算
}
int rank=1;
for(auto i=shop.begin();i!=shop.end();i++)
if(i->second>shop["memory"]) rank++; //i->first指向string,second指向int
cout<<rank<<endl;
}
shop.clear(); //清空map
}
return 0;
}
STL大法好!