1. 程式人生 > >nyist oj 138 找球號(二)(hash 表+位運算)

nyist oj 138 找球號(二)(hash 表+位運算)

pan char s geo 運算 arch font msu 哈希 next

找球號(二)

時間限制:1000 ms | 內存限制:65535 KB 難度:5
描寫敘述
在某一國度裏流行著一種遊戲。遊戲規則為:現有一堆球中。每一個球上都有一個整數編號i(0<=i<=100000000),編號可反復。另一個空箱子,如今有兩種動作:一種是"ADD",表示向空箱子裏放m(0<m<=100)個球,另一種是"QUERY”,表示說出M(0<M<=100)個隨機整數ki(0<=ki<=100000100),分別推斷編號為ki 的球是否在這個空箱子中(存在為"YES",否則為"NO")。先答出者為勝。如今有一個人想玩玩這個遊戲。但他又非常懶。

他希望你能幫助他取得勝利。

輸入
第一行有一個整數n(0<n<=10000);
隨後有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表的入門題,開始都沒接觸過用hash做的題。學數據結構的時候。這個內容也僅僅是粗略的看了一下。沒有細致去研究過,看到這道題的提示,就去把hash表的內容細致的看了一遍

http://blog.csdn.net/v_JULY_v/article/details/6256463 http://blog.csdn.net/feixiaoxing/article/details/6885657 這兩篇博客寫的都還不錯,能夠去細致看看。應該會對hash表有一定的認識。

hash表的優勢就在於高速的插入和查詢大量的數據,哈希表也有一些缺點它是基於數組的,數組創建後難於擴展某些哈希表被基本填滿時,性能下降得很嚴重。所以程序雖必需要清楚表中將要存儲多少數據(或者準備好定期地把數據轉移到更大的哈希表中,這是個費時的過程)。所以這道題目假設數組開的小了。就會超時。

以下是代碼:

#include <stdio.h>
#include <string.h>
const int maxn=1000002;
const int fib=111123;//這個值是參考別人的好像和斐波拉契有關
int Hash[maxn],head[maxn],next[maxn];//head相當於每個散列表的頭節點,當前節點的下一個節點
int top;
void add(int m)//插入元素
{
    int key=m%fib;
    next[top]=head[key];
    head[key]=top;
    Hash[top]=m;
    top++;
}
bool query(int m)//查詢元素
{
    int key=m%fib;
    for(int i=head[key];i>-1;i=next[i])
    {
        if(Hash[i]==m)
            return true;
    }
    return false;
}
int main()
{
    int n,m,num;
    char s[5];
    scanf("%d",&n);
    memset(head,-1,sizeof(head));//賦初值為-1;
    top=0;//這裏要寫在外面,先前寫在循環裏面,超時了好多次。由於僅僅是建了一個hash表
    while(n--)
    {
        scanf("%s %d",s,&m);
        if(s[0]==‘A‘)
        {
           for(int i=0;i<m;i++)
           {
                scanf("%d",&num);
                add(num);
           }
        }
        else
        {
           for(int i=0;i<m;i++)
           {
               scanf("%d",&num);
               if(query(num)) printf("YES\n");
               else printf("NO\n");
           }
        }
    }
    return 0;
}
看了一下最優代碼,是用位運算做的,對位運算還是不太熟悉,學習一下別人的寫法;

3125005怎麽來的?由於最大值是10^7+10。

用32來除法散列。(10^7+10)/32 ~~3125000.3125。所以取3125005。為什麽是用32來散列呢?數據說了數值不會超過32位。

hash表也是基於位運算的原理。

以下是代碼;

#include <cstdio>
#include <cstring>
int Hash[3125005]={0};
int main()
{
    int n,m,num;
    char s[5];
    scanf("%d",&n);
    while(n--)
    {
        scanf("%s %d",s,&m);
        if(s[0]==‘A‘)
        {
           for(int i=0;i<m;i++)
           {
                scanf("%d",&num);
                Hash[num / 32] |= 1 << (num % 32);
           }
        }
        else
        {
           for(int i=0;i<m;i++)
           {
               scanf("%d",&num);
               if(Hash[num / 32] & (1 << (num % 32))) printf("YES\n");
               else printf("NO\n");
           }
        }
    }
    return 0;
}



nyist oj 138 找球號(二)(hash 表+位運算)