STL之五:set和map

set

set就是集合。STL的set用二叉搜索树实现,集合中每个元素只出现一次,并且是排好序的。访问元素的时间复杂度是O(\log_{2}n)。

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(\log_{2}n)。

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大法好!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值