zoukankan      html  css  js  c++  java
  • ACwing 840

    维护一个集合,支持如下几种操作:

    “I x”,插入一个数x;
    “Q x”,询问数x是否在集合中出现过;
    现在要进行N次操作,对于每个询问操作输出对应的结果。

    输入格式

    第一行包含整数N,表示操作数量。

    接下来N行,每行包含一个操作指令,操作指令为”I x”,”Q x”中的一种。

    输出格式

    对于每个询问指令“Q x”,输出一个询问结果,如果x在集合中出现过,则输出“Yes”,否则输出“No”。

    每个结果占一行。

    数据范围

    1≤N≤105
    −109≤x≤109
    输入样例:
    5
    I 1
    I 2
    I 3
    Q 2
    Q 5
    输出样例:
    Yes
    No

    题目大意:

    输入一个n表示有n个操作,一共可以进行两种操作:

    • I x 将x插入到集合中
    • Q x 询问x是否在集合中,输出yes or no

    解题思路:

    一:拉链法
    哈希表模板题,找一个大于等于100000的最小素数,这里是100003,对于这里的哈希函数 h(x) = (x % N + N) % N,因为要将这些数映射到数组中,所以通过函数去寻址,O(1)的去查找集合中是否存在这个数,这里使用拉链法处理冲突,即每个数组下标接一个单链表,所有寻址为该下标的全部链接到单链表。这里用数组模拟。

    Code1:

    #include <iostream>
    #include <cstring>
    
    using namespace std;
    
    const int N = 1e5 + 3;
    
    int head[N], e[N], ne[N], idx = 0;
    
    void insert(int x)
    {
        int k = (x % N + N) % N;
        e[idx] = x;
        ne[idx] = head[k];
        head[k] = idx++;
    }
    
    bool find(int x)
    {
        int k = (x % N + N) % N;
        for (int i = head[k]; ~i; i = ne[i])
            if (e[i] == x) return true;
        return false;
    }
    
    int main()
    {
        int n;
        memset(head, -1, sizeof head);
        scanf("%d", &n);
        while (n--)
        {
            char op[2];
            int x;
            scanf("%s%d", op, &x);
            if (*op == 'I') insert(x);
            else puts(find(x) ? "Yes" : "No");
        }
        return 0;
    }
    

    二:开放寻址法
    该方法的思路是开一个两倍 - 三倍 范围的哈希表,然后将每个数映射到哈希表中,与拉链法不同的是开放寻址法不需要借助链表,而是只需要一个大于数据范围的哈希表就够了,思路还是先通过哈希函数h(x) = (x % N + N) % N寻址,然后判断该地址上的值是不是x或者为空,这里的为空并不是真的空,而是一个不在数据范围内的数 来做标记(0x3f3f3f3f > 1e9),插入操作时,先寻址,寻找null 的地址 k,直接h[k] = x即可。询问操作时,还是先寻址,寻找 x 可能所在的地址 k ,如果h[k] == null 则一定不存在,反之一定存在。

    PS:因为表的大小是远远高于数据范围的,所以不会死循环。

    Code2:

    #include <iostream>
    #include <cstring>
    
    using namespace std;
    
    const int N = 2e5 + 3;
    const int null = 0x3f3f3f3f;
    
    int h[N];
    
    int find(int x)//去寻找x可能的地址,最后返回空位null的位置或x所在的位置
    {
        int k = (x % N + N) % N;//哈希函数寻址
        while (h[k] != null && h[k] != x)
        {
            k++;
            if (k == N) k = 0;
        }
        return k;
    }
    
    int main()
    {
        int n;
        memset(h, 0x3f, sizeof h);
        scanf("%d", &n);
        while (n--)
        {
            char op[2];
            int x;
            scanf("%s%d", op, &x);
            int k = find(x);
            if (*op == 'I') h[k] = x;
            else puts(h[k] == x ? "Yes" : "No");
        }
        return 0;
    }
    
  • 相关阅读:
    数学+高精度 ZOJ 2313 Chinese Girls' Amusement
    最短路(Bellman_Ford) POJ 1860 Currency Exchange
    贪心 Gym 100502E Opening Ceremony
    概率 Gym 100502D Dice Game
    判断 Gym 100502K Train Passengers
    BFS POJ 3278 Catch That Cow
    DFS POJ 2362 Square
    DFS ZOJ 1002/HDOJ 1045 Fire Net
    组合数学(全排列)+DFS CSU 1563 Lexicography
    stack UVA 442 Matrix Chain Multiplication
  • 原文地址:https://www.cnblogs.com/Hayasaka/p/14294145.html
Copyright © 2011-2022 走看看