NYOJ 138 找球号(二) (Hash)


找球号(二)

时间限制: 1000 ms  |  内存限制: 65535 KB
难度: 5
描述
在某一国度里流行着一种游戏。游戏规则为:现有一堆球中,每个球上都有一个整数编号i(0<=i<=100000000),编号可重复,还有一个空箱子,现在有两种动作:一种是"ADD",表示向空箱子里放m(0
输入
第一行有一个整数n(0 随后有n行;
每行可能出现如下的任意一种形式:
第一种:
一个字符串"ADD",接着是一个整数m,随后有m个i;
第二种:
一个字符串"QUERY”,接着是一个整数M,随后有M个ki;

输出
输出每次询问的结果"YES"或"NO".
样例输入
2
ADD 5 34 343 54 6 2
QUERY 4 34 54 33 66
样例输出
YES
YES
NO
NO

此题的正确解法应该是Hash,但是可以用其他的方法水过

1.标准hash表

 
#include 
#include 
using namespace std;
const int maxn = 1000010;
const int fib = 111123;
int key[maxn];   
int head[maxn];    //相当于每一个散列表的头节点 
int next[maxn];    //当前节点的下一个节点
int top;

void add(int n)
{
    int temp;
    temp = n % fib;
    key[top] = n;   //在Hash表中记录下这个数值 
    next[top] = head[temp];
    head[temp] = top;
    top++;
}

int main()
{
    int n, m, number;
    char str[8];
    bool flag;
    memset(key, 0, sizeof(key));
    memset(next, 0, sizeof(next));
    memset(head, -1, sizeof(head));   //相当于把每一个映射的头结点的next都赋为NULL
    top = 0;
    scanf("%d", &n);
    while (n--){
        scanf("%s", str);
        if (str[0] == 'A'){
            scanf("%d", &m);
            for (int i = 0; i < m; i++){
                scanf("%d", &number);
                add(number);
            }
        }
        else{
            scanf("%d", &m);
            for (int i = 0; i < m; i++){
                flag = 0;
                scanf("%d", &number);
                int temp = number % fib;
                for (int j = head[temp]; j != -1; j = next[j]){
                    if (key[j] == number){
                        flag = 1;
                        break;
                    }
                }
                if (flag)
                    printf("YES\n");
                else
                    printf("NO\n");
            }
        }
    }
    return 0;
}
        

2.最优的解法

3125005怎么来的?因为最大值是10^7+10。用32来除法散列,(10^7+10)/32 ~~3125000.3125,所以取3125005。为什么是用32来散列呢?数据说了数值不会超过32位。

#include 
using namespace std;
unsigned int hash[3125005] = {0};
int main()
{
    int n, m, number;
    char str[8];
    scanf("%d", &n);
    while (n--){
        scanf("%s", str);
        if (str[0] == 'A'){
            scanf("%d", &m);
            for (int i = 0; i < m; i++){
                scanf("%d", &number);
                hash[number / 32] |= 1 << (number % 32);
            }
        }
        else{
            scanf("%d", &m);
            for (int i = 0; i < m; i++){
                scanf("%d", &number);
                if (hash[number / 32] & (1 << (number % 32)))
                    printf("YES\n");
                else
                    printf("NO\n");
            }
        }
    }
    return 0;
}

3.使用vector水过

  但是最好不要使用vectot

 
#include 
#include 
#include 
using namespace std;
vector flag(100000010);
int main()
{
    int n, m, a, b;
    char s[6];
    scanf("%d", &n);
    for (int i = 0; i < n; i++){
        scanf("%s", s);
        if (s[0] == 'A'){
            scanf("%d", &m);
            for (int i = 0; i < m; i++){
                scanf("%d", &a);
                flag[a] = 1;
            }
        }
        else{
            scanf("%d", &m);
            for (int i = 0; i < m; i++){
                scanf("%d", &b);
                if (flag[b])
                    printf("YES\n");
                else
                    printf("NO\n");
            }
        }
    }
    return 0;
}
        


你可能感兴趣的:(OJ)