题目地址:
https://www.acwing.com/problem/content/842/
维护一个集合,支持如下几种操作:
(1)I x
,插入一个数
x
x
x;
(2)Q x
,询问数
x
x
x是否在集合中出现过;
现在要进行
N
N
N次操作,对于每个询问操作输出对应的结果。
输入格式:
第一行包含整数
N
N
N,表示操作数量。接下来
N
N
N行,每行包含一个操作指令,操作指令为I x
,Q x
中的一种。
输出格式:
对于每个询问指令Q x
,输出一个询问结果,如果
x
x
x在集合中出现过,则输出Yes
,否则输出No
。每个结果占一行。
数据范围:
1
≤
N
≤
1
0
5
1\le N\le 10^5
1≤N≤105
−
1
0
9
≤
x
≤
1
0
9
-10^9\le x\le 10^9
−109≤x≤109
可以开 1 0 5 + 3 10^5+3 105+3个桶(这个数是大于 1 0 5 10^5 105的第一个质数),每个桶都存一个链表,然后用拉链法存数。这里我们可以采用头插法,而不去管集合里有重复数字的问题。代码如下:
#include <iostream>
#include <cstring>
using namespace std;
const int N = 100003;
int h[N], e[N], ne[N], idx;
void insert(int x) {
int k = (x % N + N) % N;
e[idx] = x, ne[idx] = h[k], h[k] = idx++;
}
bool find(int x) {
int k = (x % N + N) % N;
for (int i = h[k]; ~i; i = ne[i])
if (e[i] == x) return true;
return false;
}
int main() {
int n;
cin >> n;
memset(h, -1, sizeof h);
while (n--) {
char op[2];
int x;
cin >> op;
cin >> x;
if (op[0] == 'I')
insert(x);
else if (op[0] == 'Q') {
if (find(x))
cout << "Yes" << endl;
else
cout << "No" << endl;
}
}
}
每次操作期望时间复杂度 O ( 1 ) O(1) O(1)(预计哈希冲突的概率不大),空间 O ( N ) O(N) O(N)。