ACM.map

基本含义

map翻译为映射,是STL中的常用容器。其实,数组就是一种映射,比如:int a[100];就是定义了一个int到int的映射。而a[5]=25;就是把5映射到25。数组总是将int类型映射到其它基本类型(称为数组的基类型),这同时也带来了一个问题,有时候我们希望把string映射成一个int,数组就不方便了。这时就可以使用map,map可以将任何基本类型(包括STL容器)映射到任何基本类型(包括STL容器)。

常见用途

1)需要建立字符(串)与整数之间的映射,使用 map 可以减少代码量。
2)判断大整数(比如几千位)或者其他类型数据是否存在,可以把map当布尔型数组使用(哈希表),用桶排序时无法开范围特别大的数组。
3)字符串与字符串之间的映射。

使用方法

定义一个map的方法为:map<typename1,typename2> name;
其中,typename1是映射前的类型(键key),typename2是映射后的类型(值value),name为映射的名字。
普通int数组a就是map<int,int> a。而如果是字符串到整型的映射,就必须使用string,而不能使用char,即map<string,int> a。map的键和值也可以是STL容器,比如:map<set,string> mp。当然,map的键和值都是唯一的。

map的访问

通过下标访问就像普通的数组元素访问,例如先定义map<char,int> mp,然后就可以通过mp[‘c’]的方式来访问它对应的元素,如mp[‘c’]=124。
通过迭代器访问,先作如下定义:
map<typename1,typename2>::iterator it;
因为map的每一对映射都有两个typename,所以,我们使用“it->first”来访问键,而使用“it->second”来访问值。
例如:
map<string, int>::iterator p = m.begin();
p->first; // 这个是 string 值是 “one”
p->second; //这个是 int 值是 1

map的常用函数

(1)find()和 size()
find(key)是返回键为 key 的映射的迭代器,时间复杂度为 0(log 2 n),n 为 map 中映射的对数。size()用来获得map中映射的对数,时间复杂度为O(1)。
(2)clear()
clear()用来清空 map,时间复杂度为 0(n)。
(3)erase()
erase()可以删除单个元素,也可以删除一个区间内的所有元素。
删除单个元素可以用:erase(it),it为要删除的元素的迭代器,时间复杂度为O(1)。
也可以用:erase(key),key为要删除的映射的键,时间复杂度为O(log2n)。
删除一个区间内的所有元素用:erase(first,last),first为区间的起始迭代器,last为区间的末尾迭代器的下一个地址,也就是左闭右开的区间[first,last),时间复杂度为O(last-first)。

pair的定义

pair 是“二元结构体”的替代品,将两个元素捆绑在一起,节省编码时间。相当于以下定义:
struct pair{
typename1 first;
typename2 second;
}
pair有两个参数,分别对应first和second的数据类型,可以是任意基本数据类型或者容器。
定义一个pair的方法为:
pair<typename1,typename2> name;

例题

保龄球-map
Problem:A
Time Limit:1000ms
Memory Limit:65535K
Description
DL 算缘分算得很烦闷,所以常常到体育馆去打保龄球解闷。因为他保龄球已经打了几十年了,所以技术上不成问题,于是他就想玩点新花招。
DL 的视力真的很不错,竟然能够数清楚在他前方十米左右每个位置的瓶子的数量。他突然发现这是一个炫耀自己好视力的借口——他看清远方瓶子的个数后从某个位置发球,这样就能打倒一定数量的瓶子。
1 OOO
2 OOOO
3 O
4 OO
如上图,每个“O”代表一个瓶子。如果 DL 想要打倒 3 个瓶子就在 1 位置发球,想要打倒 4 个瓶子就在 2 位置发球。
现在他想要打倒 m 个瓶子。他告诉你每个位置的瓶子数,请你给他一个发球位置。
Input
第一行包含一个正整数 n,表示位置数。
第二行包含 n 个正整数,第 i 个数。表示第 i 个位置的瓶子数,保证各个位置的瓶子数不同。
第三行包含一个正整数 Q,表示 DL 发球的次数。
第四行至文件末尾,每行包含一个正整数 m,表示 DL 需要打倒 m 个瓶子。
Output
共 Q 行。每行包含一个整数,第 i 行的整数表示 DL 第 i 次的发球位置。若无解,则输出 0。
Sample Input
5
1 2 4 3 5
2
4
7
Sample Output
3
0
【数据范围】
对于 50%的数据,1 ≤ n,Q ≤ 1000,1 ≤ai,M ≤ 10^5
对于 100%的数据,1 ≤ n,Q ≤ 100000,1 ≤ai,M ≤ 10^9

由于数据范围很大,无法开数组实现对应关系,所以使用map。

#include <bits/stdc++.h>
using namespace std;
int m,n;
const int N=1e5+10;
map<int,int>vis;
int main()
{
    int n,num,a[N],cnt=0;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&num);
        vis[num]=i;//对应关系
    }
    int q;
    scanf("%d",&q);
    for(int i=1;i<=q;i++)
    {
        scanf("%d",&num);
        if(vis[num])
        a[++cnt]=vis[num];
        else
        {
            a[++cnt]=0;
        }
    }
    for(int i=1;i<=cnt;i++)
    {
        printf("%d\n",a[i]);
    }
    return 0;
}

查字典
Problem:B
Time Limit:1000ms
Memory Limit:65535K
Description
小明正在复习全国英语四级考试,他手里有一本词典,现在有很多单词要查。请编写程序帮助他快速找到要查的单词所在的页码。
Input
第 1 行 1 个正整数 N,N≤10000,表示字典中一共有多少单词。
接下来每两行表示一个单词,其中:
第 1 行是一个长度小于或等于 100 的字符串,表示这个单词,全部小写字母,单词不会重复。
第 2 行是 1 个整数,表示这个单词在字典中的页码。
接下来的一行是 1 个整数 M,M≤10000,表示要查的单词数。接下来的 M 行,每行一个字符串,表示要查的单词,保证在字典中存在。
Output
M 行,每行一个正整数,表示第 i 个单词在字典中的页码。
Sample Input
2
scan
10
word
15
2
scan
word
Sample Output
10
15

#include <bits/stdc++.h>
using namespace std;
map<string,int>vis;
int main()
{
    int n,page,m;
    ios::sync_with_stdio(false);
    string word,input;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>word>>page;
        vis[word]=page;
    }
    cin>>m;
    while(m--)
    {
        cin>>input;
        cout<<vis[input]<<endl;
    }
    return 0;
}

眼红的Medusa
Problem:C
Time Limit:1000ms
Memory Limit:65535K
Description
虽然Miss Medusa到了北京,领了科技创新奖,但是他还是觉得不满意。原因是,他发现很多人都和他一样获了科技创新奖,特别是其中的某些人,还获得了另一个奖项——特殊贡献奖。而越多的人获得了两个奖项,Miss Medusa就会越眼红。于是她决定统计有哪些人获得了两个奖项,来知道自己有多眼红。
Input
输入第一行,有两个数n,m,表示有n个人获得科技创新奖,m个人获得特殊贡献奖。
第二行,n个正整数,表示获得科技创新奖的人的编号
第三行,m个正整数,表示获得特殊贡献奖的人的编号
Output
输出一行,为获得两个奖项的人的编号,按在科技创新奖获奖名单中的先后次序输出。
注意:本题答案输出一行,最后不需要换行,否则会Presentation Error
Sample Input
4 3
2 15 6 8
8 9 2
Sample Output
2 8
Hint
对于60%的数据,n<=1000,m<=1000
对于100%的数据,n<=100000,m<=100000,获得奖项的人的编号在2e9以内
输入数据保证第二行任意两个数不同,第三行任意两个数不同。

注意按在科技创新奖获奖名单中的先后次序输出,写对应关系的时候调整位置。

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
map<int,int>vis;
int n,m,cnt,a[N],b[N],ans[N];
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    for(int i=1;i<=m;i++)
        cin>>b[i],vis[b[i]]=1;
    for(int i=1;i<=n;i++)
        if(vis[a[i]])ans[++cnt]=a[i];//根据a数组的大小顺序输出,所以对应是应该将a对应。
    for(int i=1;i<=cnt;i++)
        i==cnt?printf("%d",ans[i]):printf("%d ",ans[i]);
    return 0;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
从基础说起,内容比较全,代码详尽。 Introduction Todo List 语言相关 常见基础错误 基础知识 枚举 模拟 排序 BFS DFS 二分 动态规划 DP基础 基础DP问题 树形DP 状压DP 动态规划的优化 数据结构 并查集 树状数组 线段树 字典树 Splay ST表&划分树 树链剖分&Link;-Cut Tree 图论 强连通分量 1 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.8.1 0 1.8.1 1 1.8.1 2 1.8.1 3 1.8.1 4 1.8.1 5 1.9 1.9.1 1.9.2 1.9.3 1.9.4 1.10 1.1 0.1 1.1 0.2 1.1 0.3 1.1 1 1.1 1.1 1.1 1.2 1.1 1.3 1.1 1.4 1.1 1.5 1.1 1.6 双 联 通 分 量 割 点 和 桥 拓 扑 排 序 最 短 路 Dij k s t r a 最 短 路 S P FA 最 短 路 Flo y e d 次 短 路 与 第 K 短 路 最 近 公 共 祖 先 L C A 最 小 生 成 树 K r u s k al 最小树形图 一般图的最大匹配 最大流 Dinic 最小割 费用流 字 符 串后 缀 数 组 K M P A C 自 动 机 最 长 回 文 子 串 数 论 中 国 剩 余 定 理 扩 展 欧 几 里 得 素 数 筛 法 计 算 几 何 浮 点 数 相 关 的 陷 阱 向 量 线 段 三 角 形 多 边 形 凸 包 2 1.11.7 1.11.8 1.11.9 1.12 1.12.1 1.12.2 1.13 1.13.1 1.13.2 1.13.3 1.14 1.14.1 1.14.2 1.14.3 1.15 1.15.1 1.15.2 1.15.3 1.15.4 1.15.5 1.16 1.16.1 1.16.2 1.16.3 1.16.4 半平面 圆 三维计算几何 数学 概率 高斯消元法 组合数学 容斥原理 母函数 polya定理 搜索 A*搜索 IDA* 搜索 搜索的优化 STL相关 c++·list c++·stack & queue & priority_queue c++·set c++·map 其他语言 博弈论 巴什博弈 威佐夫博奕 Nim博弈 SG函数
一大堆模版 自己可以下来参考 应该有200个以上吧 自己下来看看 其中一个目录 图论 路径问题 0/1边权最短路径 BFS 非负边权最短路径(Dijkstra) 可以用Dijkstra解决问题的特征 负边权最短路径 Bellman-Ford Bellman-Ford的Yen-氏优化 差分约束系统 Floyd 广义路径问题 传递闭包 极小极大距离 / 极大极小距离 Euler Path / Tour 圈套圈算法 混合图的 Euler Path / Tour Hamilton Path / Tour 特殊图的Hamilton Path / Tour 构造 生成树问题 最小生成树 第k小生成树 最优比率生成树 0/1分数规划 度限制生成树 连通性问题 强大的DFS算法 无向图连通性 割点 割边 二连通分支 有向图连通性 强连通分支 2-SAT 最小点基 有向无环图 拓扑排序 有向无环图与动态规划的关系 二分图匹配问题 一般图问题与二分图问题的转换思路 最大匹配(OK) 有向图的最小路径覆盖 0 / 1矩阵的最小覆盖 完备匹配(OK) 最优匹配(OK) 稳定婚姻 网络流问题 网络流模型的简单特征和与线性规划的关系 最大流最小割定理 最大流问题(OK) 有上下界的最大流问题 循环流 最小费用最大流 / 最大费用最大流 弦图的性质和判定 组合数学 解决组合数学问题时常用的思想 逼近 递推 / 动态规划 概率问题 Polya定理 计算几何 / 解析几何 计算几何的核心:叉积 / 面积 解析几何的主力:复数 基本形 点 直线,线段 多边形 凸多边形 / 凸包 凸包算法的引进,卷包裹法 Graham扫描法 水平序的引进,共线凸包的补丁 完美凸包算法 相关判定 两直线相交 两线段相交 点在任意多边形内的判定 点在凸多边形内的判定 经典问题 最小外接圆 近似O(n)的最小外接圆算法 点集直径 旋转卡壳,对踵点 多边形的三角剖分 数学 / 数论 高精度计算 高数度加减法、乘除法 最大公约数 Euclid算法 扩展的Euclid算法 同余方程 / 二元一次不定方程 同余方程组 线性方程组 高斯消元法 解mod 2域上的线性方程组 整系数方程组的精确解法 矩阵 行列式的计算 利用矩阵乘法快速计算递推关系 分数 分数树 连分数逼近 数论计算 求N的约数个数 求phi(N) 求约数和 快速数论变换 …… 素数问题 概率判素算法 概率因子分解 数据结构 组织结构 二叉堆 左偏树 二项树 胜者树 跳跃表 样式图标 斜堆 reap 统计结构 树状数组 虚二叉树 线段树 矩形面积并 圆形面积并 关系结构 Hash表 并查集 路径压缩思想的应用 STL中的数据结构 vector deque set / map 动态规划 / 记忆化搜索 动态规划和记忆化搜索在思考方式上的区别 最长子序列系列问题 最长不下降子序列 最长公共子序列 一类NP问题的动态规划解法 树型动态规划 背包问题 动态规划的优化 四边形不等式 函数的凸凹性 状态设计 规划方向 线性规划 常用思想 二分 最小表示法 串 KMP Trie结构 后缀树/后缀数组 LCA/RMQ 有限状态自动机理论 排序 选择/冒泡 快速排序 堆排序 归并排序(OK) 基数排序 拓扑排序 排序网络
大家都是抱着对算法与数据结构极大的兴趣才参加集训的,我们也希望大家学有所成,但是刚刚接触信息学领域的同学往往存在很多困惑,不知道从何入手学习,在这篇向导里,我希望能将自己不多的经验与大家分享,希望对各位有所帮助. 一、语言是最重要的基本功 无论侧重于什么方面,只要是通过计算机程序去最终实现的竞赛,语言都是大家要过的第一道关.亚洲赛区的比赛支持的语言包括C/C++与JAVA.虽然JAVA在应用极为广泛,但是其运行速度不可恭维.而且在以往的比赛中来看,大多数队伍还是采用了C或者C++.而且C语言是大家接触的第一门编程语言,所以我们集训队都采用C和C++混编的方式写代码. 新来的同学可能C的基础知识刚刚学完,还没有接触过C++,其实在赛场上使用纯C的选手还是大有人在的,它们主要是看重了纯C在效率上的优势,所以这部分同学如果时间有限,并不需要急着去学习新的语言,只要提高了自己在算法设计上的造诣,纯C一样能发挥巨大的威力.但是我还是希望大家都能够学点C++. C++相对于C,在输入输出流上的封装大大方便了我们的操作,同时降低了出错的可能性,并且能够很好地实现标准流与文件流的切换,方便了调试的工作。如果有些同学比较在意这点,可以尝试C和C++的混编,毕竟仅仅学习C++的流操作还是不花什么时间的。 C++的另一个支持来源于标准模版库(STL),库中提供的对于基本数据结构的统一接口操作和基本算法的实现可以缩减我们编写代码的长度,这可以节省一些时间。但是,与此相对的,使用STL要在效率上做出一些牺牲,对于输入规模很大的题目,有时候必须放弃STL,这意味着我们不能存在“有了STL就可以不去管基本算法的实现”的想法;另外,熟练和恰当地使用STL必须经过一定时间的积累,准确地了解各种操作的时间复杂度,切忌对STL中不熟悉的部分滥用,因为这其中蕴涵着许多初学者不易发现的陷阱。像STL中的很多容器, vector,queue,stack,map,set等一定要比较熟悉,STL中的sort是必需要掌握的.掌握这些STL知识后写代码的时候相对于纯C会节省不少时间. C语言学习推荐:C程序设计(谭浩强编著) C++学习推荐: C++Prime, C++大学教程.(其实基本上的C++教程都行的…) STL学习推荐: C++Prime,STL标准库.(理论联系实际,边学就用学的最快) 二、以数学为主的基础知识十分重要 虽然被定性为程序设计竞赛,但是参赛选手所遇到的问题更多的是没有解决问题的思路,而不是有了思路却死活不能实现,这就是平时积累的基础知识不够。竞赛中对于基础学科的涉及主要集中于数学,此外对于物理、电路等等也可能有一定应用,但是不多。因此,大一的同学也不必为自己还没学数据结构而感到不知从何入手提高,把数学捡起来吧!下面来谈谈在竞赛中应用的数学的主要分支。 1、离散数学——作为计算机学科的基础,离散数学是竞赛中涉及最多的数学分支,其重中之重又在于图论和组合数学,尤其是图论。 图论之所以运用最多是因为它的变化最多,而且可以轻易地结合基本数据结构和许多算法的基本思想,较多用到的知识包括连通性判断、DFS和BFS,关节点和关键路径、欧拉回路、最小生成树、最短路径、二部图匹配和网络流等等。虽然这部分的比重很大,但是往往也是竞赛中的难题所在,如果有初学者对于这部分的某些具体内容暂时感到力不从心,也不必着急,可以慢慢积累。 竞赛中设计的组合计数问题大都需要用组合数学来解决,组合数学中的知识相比于图论要简单一些,很多知识对于小学上过奥校的同学来说已经十分熟悉,但是也有一些部分需要先对代数结构中的群论有初步了解才能进行学习。组合数学在竞赛中很少以难题的形式出现,但是如果积累不够,任何一道这方面的题目却都有可能成为难题。 2、数论——以素数判断和同余为模型构造出来的题目往往需要较多的数论知识来解决,这部分在竞赛中的比重并不大,但只要来上一道,也足以使知识不足的人冥思苦想上一阵时间。素数判断和同余最常见的是在以密码学为背景的题目中出现,在运用密码学常识确定大概的过程之后,核心算法往往要涉及数论的内容。 3、计算几何——计算几何相比于其它部分来说是比较独立的,就是说它和其它的知识点很少有过多的结合,较常用到的部分包括——线段相交的判断、多边形面积的计算、内点外点的判断、凸包等等。计算几何的题目难度不会很大,但也永远不会成为最弱的题。 4、线性代数——对线性代数的应用都是围绕矩阵展开的,一些表面上是模拟的题目往往可以借助于矩阵来找到更好的算法。 5、概率论——竞赛是以黑箱来判卷的,这就是说你几乎不能动使用概率算法的念头,但这也并不是说概率就没有用。关于这一点,只有通过一定的练习才能体会。而且近年来概率题出现的次数越来越多了.

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值