来自ABBYY的聪明海狸有很多爱好。其中之一就是构造高效的哈希表。哈希表中最严重的问题之一是解决冲突。海狸对这个问题很感兴趣,他决定详细研究一下。
我们假设哈希表包含h单元格,编号从0到h−1。对象被添加到和从中移除。每个对象都有自己唯一的标识符。此外,每个对象都有一个相应的哈希值——一个介于0和h−1之间的整数,包括0。当一个对象被添加到表中时,如果该对象的哈希值对应的单元格是空闲的,那么这个对象就会被添加到表中。如果单元格已被另一个对象占用,则会发生碰撞。当一个对象从表中删除时,它所占用的单元格变为空。
智能海狸最近学会了线性探测解决碰撞的方法。具体情况如下。假设添加的对象的哈希值等于t,并且表的单元格t已经被占用。然后我们尝试将这个对象添加到单元格(t+m)modh。如果它也被占用,那么我们尝试单元格(t+2⋅m)modh,然后单元格(t+3⋅m)modh,以此类推。注意,在某些情况下,可能无法将新对象添加到表中。可以保证这个问题的输入不包含这种情况。
运算amodb意味着取数a除以数b的余数。
海狸立刻觉得这种技术很不理想,于是他决定评估一下它的低效率。因此,给您一个操作序列,每个操作要么向表中添加一个对象,要么从表中删除一个对象。在添加新对象时,将执行对表的一系列调用。对已占用单元的调用称为dummy。换句话说,如果上面描述的算法的结果是对象被添加到单元格(t+i⋅m)modh (i≥0) ,那么正好执行了 i $ 虚拟调用。
您的任务是为给定的添加和删除序列计算对表的虚拟调用的总数。当一个对象从表中删除时,假设没有执行虚拟调用。在执行操作之前,表是空的,也就是说,最初它不包含任何对象。
第一行输入包含三个整数h, m和n (1≤m<h),以空格分隔,其中h是哈希表的大小,m是用于解决冲突的数字,n是操作的数量。
以下n行包含操作说明。它们的执行顺序与它们在输入文件中出现的顺序相对应。每个操作由一行描述。操作说明如下:
"+ id哈希"这是向表中添加对象的操作格式。第一个字符是“+”(ASCII 43),后跟一个空格,然后是对象标识符id (0≤id≤109),然后是另一个空格,以及给定对象的哈希值hash (0≤hash<h)。对象标识符和该对象的哈希值为整数。
"- id"从表中删除对象的操作格式。第一个字符是"-" (ASCII 45),后跟一个空格,然后是对象标识符id (0≤id≤109)。对象标识符为整数。
可以保证对于所有的加法操作,id的值是唯一的。它还保证初始数据是正确的,也就是说,总是可以向哈希表中添加对象,并且不会删除不存在的对象。
获得20分的输入限制是:
1≤n≤5000
1≤n≤5000
获得50分的输入限制是:
1≤h≤2⋅104
1≤n≤2⋅104
获得100分的输入限制为:
1≤h≤2⋅105
1≤n≤2⋅105
打印单个数字-对哈希表的虚拟调用的总数。
请不要使用%lld说明符在С++中读写64位整数。最好使用cin、cout流和%I64d说明符。
10 2 7
+ 11 0
+ 22 2
+ 33 6
+ 44 0
+ 55 0
- 22
+ 66 0
7
5 1 6
+ 123 0
+ 234 1
+ 345 2
- 234
+ 456 0
+ 567 0
4
源码:
# 智能海狸和解决碰撞
## 题目描述
来自ABBYY的聪明海狸有很多爱好。其中之一就是构造高效的哈希表。哈希表中最严重的问题之一是解决冲突。海狸对这个问题很感兴趣,他决定详细研究一下。
我们假设哈希表包含$ h $单元格,编号从$ 0 $到$ h-1 $。对象被添加到和从中移除。每个对象都有自己唯一的标识符。此外,每个对象都有一个相应的哈希值——一个介于$ 0 $和$ h-1 $之间的整数,包括$ 0 $。当一个对象被添加到表中时,如果该对象的哈希值对应的单元格是空闲的,那么这个对象就会被添加到表中。如果单元格已被另一个对象占用,则会发生碰撞。当一个对象从表中删除时,它所占用的单元格变为空。
智能海狸最近学会了线性探测解决碰撞的方法。具体情况如下。假设添加的对象的哈希值等于$ t $,并且表的单元格$ t $已经被占用。然后我们尝试将这个对象添加到单元格$ (t+m) mod\quad h $。如果它也被占用,那么我们尝试单元格$ (t+2·m) mod\quad h $,然后单元格$ (t+3·m) mod \quad h $,以此类推。注意,在某些情况下,可能无法将新对象添加到表中。可以保证这个问题的输入不包含这种情况。
运算$ a \quad mod\quad b $意味着取数$ a $除以数$ b $的余数。
海狸立刻觉得这种技术很不理想,于是他决定评估一下它的低效率。因此,给您一个操作序列,每个操作要么向表中添加一个对象,要么从表中删除一个对象。在添加新对象时,将执行对表的一系列调用。对已占用单元的调用称为dummy。换句话说,如果上面描述的算法的结果是对象被添加到单元格$ (t+i·m) mod \quad h $ $ (i\geq 0) $ $,那么正好执行了$ i $ 虚拟调用。
您的任务是为给定的添加和删除序列计算对表的虚拟调用的总数。当一个对象从表中删除时,假设没有执行虚拟调用。在执行操作之前,表是空的,也就是说,最初它不包含任何对象。
## 输入格式
第一行输入包含三个整数$ h $, $ m $和$ n $ ($ 1 \leq m<h $),以空格分隔,其中$ h $是哈希表的大小,$ m $是用于解决冲突的数字,$ n $是操作的数量。
以下$ n $行包含操作说明。它们的执行顺序与它们在输入文件中出现的顺序相对应。每个操作由一行描述。操作说明如下:
- "+ id哈希"这是向表中添加对象的操作格式。第一个字符是“+”(ASCII 43),后跟一个空格,然后是对象标识符$ id $ $ (0\leq id \leq 10^{9}) $,然后是另一个空格,以及给定对象的哈希值$ hash $ $ (0 \leq hash < h) $。对象标识符和该对象的哈希值为整数。
- "- id"从表中删除对象的操作格式。第一个字符是"-" (ASCII 45),后跟一个空格,然后是对象标识符$ id $ $ (0\leq id \leq10^{9}) $。对象标识符为整数。
可以保证对于所有的加法操作,$ id $的值是唯一的。它还保证初始数据是正确的,也就是说,总是可以向哈希表中添加对象,并且不会删除不存在的对象。
获得$20$分的输入限制是:
- $ 1 \leq n \leq 5000$
- $ 1 \leq n \leq 5000$
获得$50$分的输入限制是:
- $ 1 \leq h \leq 2·10^{4}$
- $ 1 \leq n \leq 2·10^{4}$
获得$100$分的输入限制为:
- $ 1 \leq h \leq 2·10^{5}$
- $ 1 \leq n \leq 2·10^{5}$
## 输出格式
打印单个数字-对哈希表的虚拟调用的总数。
请不要使用`%lld`说明符在С++中读写$64$位整数。最好使用`cin`、`cout`流和`%I64d`说明符。
## 样例 #1
### 样例输入 #1
10 2 7
+ 11 0
+ 22 2
+ 33 6
+ 44 0
+ 55 0
- 22
+ 66 0
### 样例输出 #1
7
## 样例 #2
### 样例输入 #2
5 1 6 + 123 0
+ 234 1
+ 345 2
- 234
+ 456 0
+ 567 0
### 样例输出 #2
4