Cod sursa(job #712081)

Utilizator katakunaCazacu Alexandru katakuna Data 13 martie 2012 00:28:48
Problema Hashuri Scor 30
Compilator cpp Status done
Runda Arhiva educationala Marime 5.13 kb
#include <cstdio>
#include <string.h>
#include <algorithm>
#include <stdlib.h>
#include <math.h>
#include <ctime>
using namespace std;

#define LL (long long)

class cockooHash {

	int tableSize;
    int maxSteps;
    int nrInsert;
    int fact;

	// h (x) = ((a * x + b) % prime) % tableSize)
	int a1, b1;
	int a2, b2;
	int prime;

	int *T1, *T2;
	bool *set1, *set2;

	void getHashFunction (int &a, int &b) {
		a = rand () % tableSize;
		b = rand () % tableSize;
	}

    void resize (int tableSize) {

        if (tableSize < this->tableSize) {

            this->tableSize = tableSize;
            this->maxSteps = (int) log2(tableSize);

            rehash ();

            this->T1 = (int *)realloc (this->T1, tableSize * sizeof (int));
            this->T2 = (int *)realloc (this->T2, tableSize * sizeof (int));

            this->set1 = (bool *)realloc (this->set1, tableSize);
            this->set2 = (bool *)realloc (this->set2, tableSize);
        }
        else {
            this->T1 = (int *)realloc (this->T1, tableSize * sizeof (int));
            this->T2 = (int *)realloc (this->T2, tableSize * sizeof (int));

            this->set1 = (bool *)realloc (this->set1, tableSize);
            this->set2 = (bool *)realloc (this->set2, tableSize);

            memset (this->set1 + this->tableSize, 0, this->tableSize);
            memset (this->set2 + this->tableSize, 0, this->tableSize);

            this->tableSize = tableSize;
            this->maxSteps = (int) log2(tableSize);

            this->rehash ();
        }

    }

	void rehash () {

		getHashFunction (this->a1, this->b1);
		getHashFunction (this->a2, this->b2);

        for (int i = 0; i < this->tableSize; ++i) {
            if (this->set1[i] == true && i != this->h1 ( this->T1[i] )) {
                this->set1[i] = 0;
                this->nrInsert--;
                this->insert ( this->T1[i] );
            }

            if (this->set2[i] == true && i != this->h2 ( this->T2[i] )) {
                this->set2[i] = 0;
                this->nrInsert--;
                this->insert ( this->T2[i] );
            }
        }
	}

	public:
	cockooHash () {

        this->fact = 3;
		this->tableSize = (this->fact);
        maxSteps = (int) log2 (tableSize);

		this->prime = 1000000009;
        this->nrInsert = 0;

		this->T1 = new int [tableSize];
		this->T2 = new int [tableSize];

		this->set1 = new bool[tableSize];
		this->set2 = new bool[tableSize];

		memset (this->T1, 0, sizeof (this->T1));
		memset (this->T2, 0, sizeof (this->T2));

		memset (this->set1, 0, sizeof (this->set1));
		memset (this->set2, 0, sizeof (this->set2));

		getHashFunction (this->a1, this->b2);
		getHashFunction (this->a2, this->b2);
	}

    int h1 (int key) {
		return ((LL this->a1 * LL key + LL this->b1) % LL this->prime ) % LL this->tableSize;
	}

	int h2 (int key) {
		return ((LL this->a2 * LL key + LL this->b2) % LL this->prime ) % LL this->tableSize;
	}

	bool find (int key) {

        if ( this->T1[ this->h1 (key) ] == key && this->set1[ this->h1 (key) ] == true) return true;
		if ( this->T2[ this->h2 (key) ] == key && this->set2[ this->h2 (key) ] == true) return true;

		return false;
	}

	bool erase (int key) {

        int success = false;
		if (this->T1[ this->h1(key) ] == key && this->set1 [ this->h1(key) ]) {
			this->set1[ this->h1 (key) ] = 0;
			success = true;
		}

		if (this->T2[ this->h2(key) ] == key && this->set2[ this->h2(key) ]) {
			this->set2[ this->h2 (key) ] = 0;
			success = true;
		}

        if (success == true) {
            this->nrInsert--;
            if ( (this->nrInsert * this->fact) < this->tableSize >> 1)
                this->resize (this->tableSize >> 1);
        }

		return success;
	}

	void insert (int key) {

		int x, y;
		int steps = 0;
        bool success = false;

		x = key;
		if ( this->set1[ this->h1 (x) ] == 0 ) {
			this->T1[ this->h1 (x)] = x;
			this->set1[ this->h1 (x) ] = 1;
			success = true;
		}

		while (success == false && steps < maxSteps) {

			steps+= 2;
		    if ( this->set2[ this->h2 (x) ] == 0 ) {
				this->set2[ this->h2 (x) ] = 1;
				this->T2[ this->h2 (x) ] = x;
				success = true;
				break;
			}

			y = this->T2[this->h2 (x)];
			this->T2[ this->h2(x) ] = x;
			x = y;

			if ( this->set1[ this->h1 (x) ] == 0 ) {
				this->set1[ this->h1 (x) ] = 1;
				this->T1[ this->h1 (x) ] = x;
				success = true;
				break;
			}

			y = this->T1[ this->h1 (x) ];
			this->T1[ this->h1 (x) ] = x;
			x = y;
		}

        if (success == true) {
            this->nrInsert++;
            if ( (this->nrInsert * this->fact) > this->tableSize)
                this->resize (this->tableSize << 1);

            return ;
        }

        this->rehash ();
        this->insert (key);
	}

};

int main () {

    freopen ("hashuri.in", "r", stdin);
    freopen ("hashuri.out", "w", stdout);

    srand ( time (0) );

    cockooHash myHash;
    int nr = 0;

    int T, tip, key;
    scanf ("%d", &T);
    for (; T; T--) {
        scanf ("%d %d", &tip, &key);

        if (tip == 1 && !myHash.find (key)) myHash.insert (key);
        if (tip == 2 && myHash.find (key))
            myHash.erase (key);
        if (tip == 3)
            printf ("%d\n", (int) myHash.find (key));
    }

    return 0;
}