map

map 的意思是映射。用法一般是

                 map<char, int>mp

按照我的理解,map 类似于一个高级的数组。前面的数据类型 char 相当于下脚标,而数组元素的值就对应着后面的类型 int。例如可以用一个 map<string, int>month_name 来表示“月份名字对应的月份编号“。然后用 month_name["july"] = 7 这样的方式来赋值。所以说,”高级的数组“指下脚标和元素类型可以是任意数据类型的(当然包括结构体)。

接下来说说基本操作

1.声明,赋值

除了上面已经讲过的像数组元素那样赋值的方法, 还支持这样 mp.insert(make_pair(”july“, 7)); (不过当然是上面的方法简单)

2.查找

和 set 很像:if (mp.find('f') == mp.end()) ......,若找不到,就执行 if 里面的语句。(找的是下脚标,不是元素的值)

3. 输出大小

同理 set :mp.size()

4.遍历

 #include <bits/stdc++.h>
using namespace std;
map<char, int>mp;
int main()
{
for (int i = ; i < ; i++) mp['a' + i] = i;
for (map<char, int>::iterator it = mp.begin(); it != mp.end(); ++it)
printf("%c %d\n", it -> first, it -> second);
/*若嫌麻烦,也可在前面用 typedef 改个名,以后遍历就不用写一串了
typedef map<char, int>::iterator mcit;
for(mcit it = mp.begin(); it != mp.end(); ++it) */
return ;
}

输出:

a 0

b 1

c 2

d 3

e 4

还有 first 就是指“下脚标”, second 指”数组元素值“。

5.删除

和 set 一样

mp.erase('f');  或  map<char, int>::iterator it = mp.find('f'); mp.erase(it);

6. lower_bound() 和 upper_bound()

map<char, int>::iterator it1 = mp.lower_bound('f'); printf("%c %d\n", it1->first, it1->second); 就这样

7.!注意 !

看这段代码

 #include <bits/stdc++.h>
using namespace std;
map<char, int>mp;
int main()
{
for (int i = ; i < ; i++) mp['a' + i] = i;
cout << mp['z'] << endl;
for (map<char, int>::iterator it = mp.begin(); it != mp.end(); ++it)
printf("%c %d\n", it -> first, it -> second);
return ;
}

在第7行,我们发现 mp['z'] 根本没有,然而这是能过编译的!而且输出时,结果是这样的:

0

a 0

b 1

c 2

d 3

e 4

z 0

可见 mp['z'] 的值是0。而且这个 mp['z'] 也被自动添加到了 mp 中,看来c++是自己在 mp 中创建了一个 mp['z']。所以我们凡是要对 map 进行操作时,都要首先确认这个元素是否存在,否则就会出现这些像意想不到的错误。

multimap

multimap的用法几乎map一样,唯一不同的是,它里面的元素是可以重的。

所以两种删除方法在这里就不一样了:

1.mp.erase('f'):删除multimap中所有以'f'为下标的元素。

2. map<char, int>::iterator it = mp.find('f'); erase(it):只删除第一个‘’f.

应用

1.map可以代替hash

  虽然复杂度多了一个log,但是在时间充裕而且代码比较长的情况下,用map写就显得极为方便。

  举一个很水的例子:洛谷P3370 【模板】字符串哈希

 #include<cstdio>
#include<string>
#include<map>
using namespace std; map<string, bool> mp;
int n, cnt = ;
char s[]; int main()
{
scanf("%d", &n);
for(int i = ; i <= n; ++i)
{
scanf("%s", s);
if(!mp[s]) mp[s] = , cnt++;
}
printf("%d\n", cnt);
return ;
}

2.解决一些比较麻烦的记录问题

  如果你看不懂这个标题在说啥,说明语文学得不好。不管了,直接上题:家谱

  这道题确实是并查集水题,但是我们要记录出现过的字符串,这时候就是map大显神威的时候了。我这篇博客里讲的挺细的,简单易懂。

  不过里面可以不用string类型输入,而用字符数组,只不过map的类型是map<string, int>。

3.优!化!

  别看map带一个log,但在某些情况下还能优化!

  [九省联考2018]一双木棋chess

  没错,去年的辽宁省选Day1T1。

  解法是对抗搜索,但这不是我们今天的重点。

  暴力的搜索还要判断每一行的状态,多了一层复杂度,导致后几个点TLE。如果把状态压成一个数的话不仅数组装不下,int都会爆。因此我们把表示状态的long long当成map的下标,然后找状态的时候时间复杂度成功降到了logn。虽然不是最优的,但是AC已经绰绰有余了。最重要的是,这个优化也别好想,随手就是一加。

放个代码吧(有人是不是想c-c + c-v瞬间A题)

 #include<cstdio>
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
typedef long long ll;
const int maxn = ;
//mrclr struct Node
{
int x, y;
}a[maxn][maxn];
struct Node2
{
int xx, yy, cha2;
bool operator < (const Node2& other)const
{
return cha2 < other.cha2;
}
};
int n, m;
const int INF = 0x3f3f3f3f;
struct Node3
{
int a[maxn];
ll encode()const
{
ll ret = ;
for(int i = ; i <= n; ++i) {ret |= a[i]; ret <<= ;}
return ret;
} }chess;
map<ll, int> mpMax, mpMin;
int Minsearch(const Node3& chess);
int Maxsearch(const Node3& chess)
{
if(chess.a[n] == m) return ;
if(mpMax.find(chess.encode()) != mpMax.end()) return mpMax[chess.encode()];
int Max = -INF;
for(int i = ; i <= n; ++i)
if(chess.a[i] < chess.a[i - ])
{
Node3 _ch = chess;
_ch.a[i]++;
Max = max(Max, a[i][_ch.a[i]].x + Minsearch(_ch));
}
return mpMax[chess.encode()] = Max;
}
int Minsearch(const Node3& chess)
{
if(chess.a[n] == m) return ;
if(mpMin.find(chess.encode()) != mpMin.end()) return mpMin[chess.encode()];
int Min = INF;
for(int i = ; i <= n; ++i)
if(chess.a[i] < chess.a[i - ])
{
Node3 _ch = chess;
_ch.a[i]++;
Min = min(Min, -a[i][_ch.a[i]].y + Maxsearch(_ch));
}
return mpMin[chess.encode()] = Min;
}
int main()
{
scanf("%d%d", &n, &m);
for(int i = ; i <= n; ++i)
for(int j = ; j <= m; ++j) scanf("%d", &a[i][j].x);
for(int i = ; i <= n; ++i)
for(int j = ; j <= m; ++j) scanf("%d", &a[i][j].y);
for(int i = ; i <= n; ++i) chess.a[i] = ;
chess.a[] = m;
printf("%d\n", Maxsearch(chess));
return ;
}

map讲到这里就算讲完了,如果有更好的用法,欢迎在下面评论,或者当面diss mrclr。

map && multimap的更多相关文章

  1. STL中的map/multimap小结

    (1)使用map/multimap之前必须包含头文件<map>:#include<map> 并且和所有的关联式容器一样,map/multimap通常以平衡二叉树来完成 (2)n ...

  2. C++ map multimap

    map multimap map,multimap key-value对容器,也叫字典,map中不能存放key相同的元素,而multimap可以,容器中元素默认按升序排序 map multimap的相 ...

  3. STL:map/multimap用法详解

    map/multimap 使用map/multimap之前要加入头文件#include<map>,map和multimap将key/value当作元素,进行管理.它们可根据key的排序准则 ...

  4. iBinary C++STL模板库关联容器之map/multimap

    目录 一丶关联容器map/multimap 容器 二丶代码例子 1.map的三种插入数据的方法 3.map集合的遍历 4.验证map集合数据是否插入成功 5.map数据的查找 6.Map集合删除元素以 ...

  5. 09--STL关联容器(map/multimap)

    一:map/multimap的简介 map是标准的关联式容器,一个map是一个键值对序列,即(key,value)对.它提供基于key的快速检索能力. map中key值是唯一的.集合中的元素按一定的顺 ...

  6. c/c++ 标准库 map multimap元素访问

    标准库 map multimap元素访问 一,map,unordered_map下标操作 下标操作种类 功能描述 c[k] 返回关键字为k的元素:如果k不在c中,添加一个关键字为k的元素,并对其初始化 ...

  7. STL之六:map/multimap用法详解

    转载于:http://blog.csdn.net/longshengguoji/article/details/8547007 map/multimap 使用map/multimap之前要加入头文件# ...

  8. STL之map&multimap使用简介

    map 1.insert 第一种:用insert函数插入pair数据 #include <map> #include <string> #include <iostrea ...

  9. STL——容器(Map & multimap)的删除

    Map & multimap 的删除 map.clear();           //删除所有元素 map.erase(pos);      //删除pos迭代器所指的元素,返回下一个元素的 ...

  10. STL——容器(Map & multimap)的大小

    1. Map & multimap 的大小 map.size();     //返回容器中元素的数目 map.empty();//判断容器是否为空, 容器中有内容将会返回 false 代码示例 ...

随机推荐

  1. netty源码解解析(4.0)-1 核心架构

    netty是java开源社区的一个优秀的网络框架.使用netty,我们可以迅速地开发出稳定,高性能,安全的,扩展性良好的服务器应用程序.netty封装简化了在服务器开发领域的一些有挑战性的问题:jdk ...

  2. 基于vue框架手写一个notify插件,实现通知功能

    简单编写一个vue插件,当点击时触发notify插件,dom中出现相应内容并且在相应时间之后清除,我们可以在根组件中设定通知内容和延迟消失时间. 1. 基础知识 我们首先初始化一个vue项目,删除不需 ...

  3. SpringMVC4+Hibernate5+SQLServer 2014 整合(包括增删改查分页)

    前言 前面整合完了SpringMVC+MyBatis,自然也少不了SpringMVC+Hibernate,严格来说Hibernate才是我们真正想要的ORM框架么.只记得最初学习hibernate时, ...

  4. [design-patterns]设计模式之一策略模式

    设计模式 从今天开始开启设计模式专栏,我会系统的分析和总结每一个设计模式以及应用场景.那么首先,什么是设计模式呢,作为一个软件开发人员,程序人人都会写,但是写出一款逻辑清晰,扩展性强,可维护的程序就不 ...

  5. windows server 证书的颁发与IIS证书的使用

    最近工作业务要是用服务器证书验证,在这里记录下一. 1.添加服务器角色 [证书服务] 2.一路下一步直到证书服务安装完成; 3.选择圈选中的服务器证书 4.点击[创建证书申请] 5.填写信息 6.下一 ...

  6. angularjs通过ng-change和watch两种方式实现对表单输入改变的监控

    angularjs通过ng-change和watch两种方式实现对表单输入改变的监控 直接上练习代码 <!DOCTYPE html> <html xmlns="http:/ ...

  7. 命令查看当前电脑安装所有版本.NET Core SKD

    dotnet --version 查看当前使用版本 dotnet --info 安装的所有版本 包括版本地址 也可用命令帮助 dotnet help

  8. 【原】通过BeanNameAutoProxyCreator改变臃肿代码

    前言: 最近接手了一个项目,大概过了下需求,然后打开项目准备开搞的时候发现一个问题,这个项目是提供rest服务的一个web项目,其中很多旧系统由于还没改成微服务,所以只能通过HttpClient发起调 ...

  9. 【Java深入研究】6、CGLib动态代理机制详解

    一.首先说一下JDK中的动态代理: JDK中的动态代理是通过反射类Proxy以及InvocationHandler回调接口实现的 但是,JDK中所要进行动态代理的类必须要实现一个接口,也就是说只能对该 ...

  10. java_分解质因数

    题目内容: 每个非素数(合数)都可以写成几个素数(也可称为质数)相乘的形式,这几个素数就都叫做这个合数的质因数.比如,6可以被分解为2x3,而24可以被分解为2x2x2x3. 现在,你的程序要读入一个 ...