zoukankan      html  css  js  c++  java
  • map && multimap

    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.遍历

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

    输出:

    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 ", it1->first, it1->second); 就这样

    7.!注意 !

    看这段代码

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 map<char, int>mp;
     4 int main()
     5 {
     6     for (int i = 0; i < 5; i++) mp['a' + i] = i;
     7     cout << mp['z'] << endl;
     8     for (map<char, int>::iterator it = mp.begin(); it != mp.end(); ++it)
     9         printf("%c %d
    ", it -> first, it -> second);
    10     return 0;
    11 }

    在第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 【模板】字符串哈希

     1 #include<cstdio>
     2 #include<string>
     3 #include<map>
     4 using namespace std;
     5 
     6 map<string, bool> mp;
     7 int n, cnt = 0; 
     8 char s[1505];
     9 
    10 int main()
    11 {
    12     scanf("%d", &n);
    13     for(int i = 1; i <= n; ++i)
    14     {
    15         scanf("%s", s);
    16         if(!mp[s]) mp[s] = 1, cnt++;
    17     }
    18     printf("%d
    ", cnt);
    19     return 0;
    20 }
    View Code

    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题)

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<cstdlib>
     5 #include<cstring>
     6 #include<algorithm>
     7 #include<map>
     8 using namespace std;
     9 typedef long long ll;
    10 const int maxn = 15;
    11 //mrclr
    12 
    13 struct Node
    14 {
    15   int x, y;      
    16 }a[maxn][maxn];
    17 struct Node2
    18 {
    19   int xx, yy, cha2;
    20   bool operator < (const Node2& other)const
    21   {
    22     return cha2 < other.cha2; 
    23   }
    24 };
    25 int n, m;
    26 const int INF = 0x3f3f3f3f;
    27 struct Node3
    28 {
    29     int a[maxn];
    30     ll encode()const
    31     {
    32         ll ret = 0;
    33         for(int i = 1; i <= n; ++i) {ret |= a[i]; ret <<= 5;}
    34         return ret;  
    35     }
    36     
    37 }chess;
    38 map<ll, int> mpMax, mpMin;
    39 int Minsearch(const Node3& chess);
    40 int Maxsearch(const Node3& chess)
    41 {
    42     if(chess.a[n] == m) return 0;
    43     if(mpMax.find(chess.encode()) != mpMax.end()) return mpMax[chess.encode()];
    44     int Max = -INF;
    45     for(int i = 1; i <= n; ++i)
    46         if(chess.a[i] < chess.a[i - 1])
    47         {
    48             Node3 _ch = chess;
    49             _ch.a[i]++;
    50             Max = max(Max, a[i][_ch.a[i]].x + Minsearch(_ch));             
    51         }
    52     return mpMax[chess.encode()] = Max;
    53 }
    54 int Minsearch(const Node3& chess)
    55 {
    56     if(chess.a[n] == m) return 0;
    57     if(mpMin.find(chess.encode()) != mpMin.end()) return mpMin[chess.encode()];
    58     int Min = INF;
    59     for(int i = 1; i <= n; ++i)
    60         if(chess.a[i] < chess.a[i - 1])
    61         {
    62             Node3 _ch = chess;
    63             _ch.a[i]++;
    64             Min = min(Min, -a[i][_ch.a[i]].y + Maxsearch(_ch));             
    65         }
    66     return mpMin[chess.encode()] = Min;
    67 }
    68 int main()
    69 {
    70   scanf("%d%d", &n, &m);
    71   for(int i = 1; i <= n; ++i)
    72     for(int j = 1; j <= m; ++j) scanf("%d", &a[i][j].x);
    73   for(int i = 1; i <= n; ++i)
    74     for(int j = 1; j <= m; ++j) scanf("%d", &a[i][j].y);
    75   for(int i = 1; i <= n; ++i) chess.a[i] = 0;
    76   chess.a[0] = m;
    77   printf("%d
    ", Maxsearch(chess)); 
    78   return 0;
    79 } 
    View Code

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

  • 相关阅读:
    AcWing 157. 树形地铁系统 (hash判断树同构)打卡
    AcWing 156. 矩阵 (哈希二维转一维查询)打卡
    AcWing 144. 最长异或值路径 01字典树打卡
    AcWing 143. 最大异或对 01字典树打卡
    AcWing 142. 前缀统计 字典树打卡
    AcWing 139. 回文子串的最大长度 hash打卡
    AcWing 138. 兔子与兔子 hash打卡
    常用C库函数功能及用法
    编程实现C库函数
    C语言面试题5
  • 原文地址:https://www.cnblogs.com/mrclr/p/8410709.html
Copyright © 2011-2022 走看看