Cod sursa(job #921907)

Utilizator R.A.RFMI Romila Remus Arthur R.A.R Data 21 martie 2013 20:25:31
Problema Hashuri Scor 40
Compilator cpp Status done
Runda Arhiva educationala Marime 3.58 kb
#include <iostream>
#include <fstream>
#include <time.h>
#include <stdlib.h>
#include <cstring>

using namespace std;

template<class T>
class Cuckoo
{
private:
        int RM,C1, C2, T1, T2,Disp1,Disp2,K;
        T *Hash1,*Hash2,*Nr;
        T NUL;
        bool *Op;
        bool Add(T);
        void Rehash();
        void Generate();
        int F1(T x){return ToInt(x)%Disp1;}
        int F2(T x){return ToInt(x)%Disp2;}
        int ToInt(int);
        int ToInt(long long);
        int ToInt(string);
        int ToInt(double);
        int ToInt(float);
        void Swap(T &a,T &b){T c = a; a = b; b = c;}

public:
        Cuckoo(int);
        void Insert(T);
        bool Find(T);
        void Delete(T);
};

template<class T>
int Cuckoo<T>::ToInt(int x)
{
    NUL = 0;
    return x;
}

template<class T>
int Cuckoo<T>::ToInt(long long x)
{
    NUL = 0;
    int ret = x;
    return x;
}

template<class T>
int Cuckoo<T>::ToInt(string x)
{
    int i;
    unsigned int ret = 0;
    for(NUL = "",i=0;i<x.size();i++)
        ret+=x[i],ret*=31,ret%=2000000;
    return (int)ret;
}

template<class T>
int Cuckoo<T>::ToInt(double x)
{
    NUL = 0;
    long long _int = (1<<31);
    long long ret = ((long long)((x*0.618034)*100000))%_int;
    return ret%_int;
    return ret;
}

template<class T>
int Cuckoo<T>::ToInt(float x)
{
    NUL = 0;
    long long _int = (1<<31);
    long long ret = ((long long)((x*0.618034)*100000))%_int;
    return ret%_int;
    return ret;
}

template<class T>
void Cuckoo<T>::Generate()
{
    Disp1 = C1 + rand()%T1;
    Disp2 = C2 + rand()%T2;
}

template<class T>
Cuckoo<T>::Cuckoo(int N = 1000000)
{
    RM = 29, C1 = 1211237, C2 = 912041, T1 = 1000000, T2 = 200000;
    srand(time(NULL));
    Generate();
    Hash1 = new T[Disp1+1];
    Hash2 = new T[Disp2+1];
    Op = new bool[N+1];
    Nr = new T[N+1];
    K = 0;
}

template<class T>
bool Cuckoo<T>::Add(T nr)
{
    int i;
    for(i=1;i<=RM;i++)
    {
        if(Hash1[F1(nr)] == NUL)
        {
            Hash1[F1(nr)] = nr;
            return 1;
        }
        Swap(nr,Hash1[F1(nr)]);
        if(Hash2[F2(nr)] ==NUL)
        {
            Hash2[F2(nr)] = nr;
            return 1;
        }
        Swap(nr,Hash2[F2(nr)]);
    }
    return 0;
}

template<class T>
void Cuckoo<T>::Insert(T nr)
{
    Op[++K] = 1, Nr[K] = nr;
    if(!Add(nr))
        Rehash();
}

template<class T>
void Cuckoo<T>::Delete(T nr)
{
    Op[++K] = 0, Nr[K] = nr;
    int v1 = F1(nr), v2 = F2(nr);
    if(Hash1[v1] == nr)
        Hash1[v1] = NUL;
    if(Hash2[v2] == nr)
        Hash2[v2] = NUL;
}

template<class T>
void Cuckoo<T>::Rehash()
{
    delete[] Hash1;
    delete[] Hash2;
    Generate();
    Hash1 = new T[Disp1+1];
    Hash2 = new T[Disp2+1];
    for(int i=1;i<=K;i++)
    {
        if(Op[i])
        {
            if(!Find(Nr[i]))
             if(!Add(Nr[i]))
             {
                Rehash();
                return;
             }
        }
        else Delete(Nr[i]);
    }
}

template<class T>
bool Cuckoo<T>::Find(T nr)
{
    int v1 = F1(nr), v2 = F2(nr);
    if(Hash1[v1] == nr || Hash2[v2] == nr)
        return 1;
    return 0;
}


int main()
{
    int x;
    int op,N;
    ifstream in("hashuri.in");
    ofstream out("hashuri.out");
    in>>N;
    Cuckoo<int> A(N);
    while(N--)
    {
        in>>op>>x;
        if(op==1)
            A.Insert(x);
        if(op==2)
            A.Delete(x);
        if(op==3)
            out<<A.Find(x)<<'\n';
    }
    return 0;
}