map关联容器使用详解
咳咳,马上就要期末考试了,说实话有些科目还是有点方的,有些课一直没有听,也没有去练习,然后最近几日还要去赶双创的项目,害。。。。按照流程,今天来讲讲map关联容器的使用,咳咳,冲冲冲。。。
- 首先哈,来讲一个问题。
- 有n个学生,然后每个人都有姓名name和学号id,现在给定一个学生的name,要求查找他的id。
- 那么通常情况下呢,我们会建立一个自定义一个数据结构,里面有name和id两个变量,然后进行储存。
- 如此,也能实现数据的存储的查询,但是每次查询的复杂度都是O(n)级别的,效率贼低,这并不能满足我们算法复杂度的需要,那么有什么办法能够更快一点呢。答案还是有的,那就是今天我们要学习的map关联容器。
- 这玩意算的上是算法里面用的最多的了,反正就是贼好用。
- map他是一个关联容器,他实现从 键 到值的 值 的映射,内部的函数实现是用平衡二叉树实现了,复杂度也是对数极的,效率高。
- 用map来写第一个问题,那就太简单了,直接起飞。
- map的定义呢,里面是两个数据类型,第一个类型表示的是 键key 的类型,第二个类型表示这 值value 的类型。类型可以随意的,你需要映射什么类型就设置什么类型。例如:
#include<bits/stdc++.h>
using namespace std;
int main(){
map<string , int > a; //表示字符映射整型。
a["xiaoming"]=21; //map容器的输入,表示小明19岁了。
cout << a["xiaoming"] << endl; //map容器的输出 ,直接输出小明的岁数
}
- 好滴,这个输入输出已经会了,那接下来看看map容器的遍历和 键值的引用吧!
- 咳咳,可以看出哈! 我们使用 it->first 引用的是 键key ,然后 it->second 引用的是 值value 。
- 这样子哈,我们基本上就会了,然后我们直接来实战试试。
hdu 2648 “Shopping”
题目链接:点我了解题目(这是一个链接)
题目描述:
每个女孩都喜欢购物,蒲公英也喜欢。现在,由于春节临近,她发现这家商店每天都在涨价。她喜欢一家叫做“记忆”的商店。现在她想知道每天更换后这家商店的价格等级。
输入描述:
一行包含一个数字n(n <= 10000),代表商店的数量。
然后n行,每行包含一个字符串(长度小于31,并且仅包含小写字母和大写字母。)代表商店的名称。
然后一行包含一个数字m(1 <= m <= 50),代表天。
然后m个零件,每个零件包含n条线,每条零件包含数字s和字符串p,代表这一天,商店p的价格增加了s。
输出描述:
包含m行,在第i行后第i行打印多个商店“内存”的等级。我们将等级定义为:如果有t家商店的价格高于“内存”,则其等级为t + 1。
输入样例:
3
memory
kfc
wind
2
49 memory
49 kfc
48 wind
80 kfc
85 wind
83 memory
输出样例:
1
2
- 先将每个物品进map,设置初始价格为0,后面入值的时候直接 map[物品名称]+=物品增长价值 ,然后利用迭代器进行遍历一次,算出高于memory商品的店数有多少即可。
- 咳咳,好了,开打。
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
map<string , int > a; //建立商品名称到商品价格的映射
cin >> n; //n个商品
while(~scanf("%d",&n)){ //多组输出值
a.clear();
for(int i=0;i<n;i++){
string str;
cin >> str;
a[str]=0; //商品初始价格都是0
}
int m; //m表示天数,v表示当日某商品的增长价格
cin >> m;
while(m--){
int ans=0;
for(int i=0;i<n;i++){
string str;
int v;
cin >> v >> str;
a[str]+=v;
}
map<string,int>::iterator it;
for(it=a.begin();it!=a.end();it++){
if(a["memory"]<it->second)ans++;
}
cout << ans+1 << endl;
}
}
return 0;
}
- 噗,我真吐了,第二次AC,原因是题目是要求多组输入,所有整个程序要进循环的。
- emmm真菜。
- 这里说一下哈,提交偷懒的话,尽量用G++提交,为什么呢,因为c++他不支持万能库,就是#include<bits/stdc++.h>这是个万能库。
- 写个这玩意,啥库都能调用了,当然啦,有优点就有缺点,这样虽然你爽了, 但是电脑很不爽,他相对于你单独把那些库写出来,时间上会慢一点,比赛的时候建议还是自己写需要的库名称,平时的话,还是自己爽重要一点,啊哈哈哈哈哈。
- 反正就是觉得,map跟字符串很配哦,就是好用。
- 来来来,我们再来搞一道字符串问题,用map做,超级简单。
hdu 1251 “统计难题”
题目连接:点我了解题目(这是一个链接)
题目描述:Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀).
输入样例:
banana
band
bee
absolute
acm
ba
b
band
abc
输出样例:
2
3
1
0
- 我们先分析一波,首先,一个字符串有多少个前缀呢,比如:abcd 的前缀有 a,ab,abc,abcd; 所有我们只需要把这四个投入到map里面后,自加一次就可以了,现在就是如何进行分开投入。
- 这样,倒过来看, abcd,abc,ab,a; 这样子,我们知道,一个字符串是以它的反斜杠零为结束标志的,我们只需要从后面开始,依次变成反斜杠零就可以了。
- 好了,知道这个我们就可以直接开打了。
#include<bits/stdc++.h>
using namespace std;
int main(){
char s[100];
map<string ,int >mp;
while(gets(s)){
int len = strlen(s);
if(len==0)break; //表示投入了一个回车换行,直接跳出。
for(int i=len;i>0;i--){
s[i]=0; //注意,在字符串里面,0和'\0'是一样的。
mp[s]++;
}
}
while(gets(s)){
if(strlen(s)==0)break;
cout << mp[s] << endl;
}
return 0;
}
- 注意哦,这里不能用string 引用字符串类型,因为string并不是以\0为结束标志的字符串。
- 虽然显示是一样的,但是内部长度还是不一样的,string中0也会当做字符中一的一个字符存入。
- 咳咳,可能是因为strlen这个函数,他是以‘\0’为结束标志的,但是length,就是直接求出他的长度的。嗯嗯,就是这样。
- 行,今天的map就到这里了。
- 今天很兴奋,遇到了字符串问题,前面有说过,字符串和map容器很配哦!
ICPC Chennai 2017 B - Minimize the string
题目链接:点我了解题目(这是一个链接)
题目大意:给您n个字符串s 1,s 2,…,s n。每个字符串仅包含字母“ a”和“ b”,每个字符串的长度最多为2。换句话说,唯一允许的字符串是“ a”,“ b”,“ aa”,“ ab”,“ ba”和“ bb”。
考虑一个置换p = { p 1,p 2,…,p Ñ }整数的{1,2,…,Ñ }。使用此置换,您可以获得新的字符串S = s p 1 + s p 2 + … + s p n,其中运算符+表示字符串的串联。
您可以通过多次执行以下操作来缩短字符串S:选择两个连续相等的字符,然后从字符串中删除这些字符之一。例如,字符串“ aabb”可以在一个操作中缩短为“ abb”或“ aab”,然后可选地,仍可以将其缩短为“ ab”。
您可以选择任何排列p。取用此置换获得的字符串S,并使用任何操作序列,使字符串长度最小。找到可获得的字符串的最小可能长度。
输入样例:
2
2
ba ab
4
a b a b
输出样例:
3
2
- 题目还是很简单的,就是相等的字符可以互相抵消。
- 题目还是横简单了,俺又犯傻了,导致错了三次,原因是循环里面用来两个一样变量,害,难受呀!
#include<bits/stdc++.h>
using namespace std;
int main(){
int t;
cin >> t;
while(t--){
int n;
cin >> n;
string s;
map<string , int >mp;
for(int i=0;i<n;i++){
cin >> s;
string str="";
int f1=1,f2=1;
for(int j=0;j<s.length();j++){
if(s[j]=='a'&&f1){str+="a";f1=0;}
if(s[j]=='b'&&f2){str+="b";f2=0;}
}
mp[str]++;
}
if(mp["ab"]==0&&mp["ba"]==0)
if(mp["a"]&&mp["b"])cout << 2 << endl;
else cout << 1 << endl;
else{
if(mp["ab"]==0||mp["ba"]==0){
if(mp["ab"])cout << mp["ab"]*2 << endl;
else cout << mp["ba"]*2 << endl;
}
else{
if(mp["ab"]==mp["ba"])cout << 2*mp["ab"]+1 << endl;
else cout << max(mp["ab"],mp["ba"])*2 << endl;
}
}
mp.clear();
}
return 0;
}
- 咳咳,溜了溜了。晚上练习ICPC遇到这玩意,害,气死我了。