EOJ刷题记录第六弹
unordered_map中count()与[]的区别
unordered_map 的 count(key) 方法的目的是 专门用来检查键 key 是否存在于 map 中。
1. unordered_map 的 [] 运算符的行为
在 C++ 的 unordered_map 中,当你使用 [] 运算符访问一个键(例如 pos[remain])时,会发生以下情况:
- 如果键 remain 已经存在于 pos 中: pos[remain] 会返回对 已存在的值 的引用(reference)。你可以读取或修改这个已存在的值。
- 如果键 remain 不存在于 pos 中:
- pos[remain] 会在 pos 中 插入一个新的键值对。
- 键是 remain。
- 值是该值类型的 默认值。对于 int 类型,默认值是 0。
- pos[remain] 最终会返回对这个 新插入的默认值 0 的引用。
if (pos[remain] != 0) 的问题
当你使用 if (pos[remain] != 0) 时,你的意图是检查 “余数 remain 是否已经出现过(即是否在 pos 中有记录)”。 但是,由于 pos[remain] 的行为,这个判断会产生误导:
- 情况一:remain 已经出现过,并且在 pos 中有记录,假设记录的位置不是 0 (虽然我们的代码中位置 idx 从 0 开始,但这里为了普遍性假设位置值可以是任何非负整数)。 此时 pos[remain] 返回的是之前记录的位置值 (非零值),所以 if (pos[remain] != 0) **条件为真 (true)**,这似乎是正确的,因为余数确实出现过了。
- 情况二:remain 第一次出现,之前没有在 pos 中记录。 此时 pos[remain] 会 插入新的键 remain,并赋值为默认值 0,然后返回对这个 0 值的引用。 因此, if (pos[remain] != 0) **条件为假 (false)**,这 也是正确的,因为余数是第一次出现。
- 情况三:remain 第一次出现,但是 pos 中 *已经存在* 键 remain,并且其对应的值 *恰好是 0* (这种情况在你的代码逻辑中其实不应该发生,因为一旦余数出现过,我们就会记录它的位置 idx,idx 是递增的,除非循环节起始位置恰好是 0,但那也是一个有效的位置,不应该被误判)。 这种情况比较微妙,但在你的代码逻辑中,如果循环节的起始位置恰好是索引 0, 并且你之前错误地使用了 if(pos[remain] != 0), 可能会导致逻辑错误,虽然在这个特定问题中不太容易直接体现出来,但这是一个潜在的隐患。
更严重的问题 (隐藏的副作用):
即使在某些情况下 if (pos[remain] != 0) 看起来好像能工作,但 最根本的问题是 pos[remain] 会在你 *检查* 的同时 *修改* pos 本身 (如果键不存在时会插入默认值)。 这是一种 副作用,使得你的代码逻辑变得不清晰和难以维护。你本意只是想 判断是否存在,结果却意外地 修改了数据结构。
Problem #2896 - ECNU Online Judge
读取一行字符串(包括空格)应该怎么处理
- getchar()是读取一个字符,getline()读取的已经包含’\n’
- getline(cin, str) 读取一行
- istringstream 一个变量(str); 构造istringstream
- while(一个变量 >> string); istringstream类用空格划分读入到string
Problem #1018 - ECNU Online Judge
string 常用技巧
截断子串
1 | string tmp = tar; |
CodeBlocks设置代码补全
setting->editor->Code completion
- Keyword sets to additionally include1~9全部勾中
- 延迟200ms