Cod sursa(job #1710616)

Utilizator AlexandruValeanuAlexandru Valeanu AlexandruValeanu Data 29 mai 2016 13:34:38
Problema Hashuri Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.08 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <memory>
#include <limits>

using namespace std;

template<typename T, typename V>
class HashTable
{
private:

    const int numberOfPrimes = 8;
    const vector<int> primes{61,67,71,73,79,83,89,97};

    int prime;

    int generatePrime()
    {
        srand(time(nullptr));
        return primes[rand() % numberOfPrimes];
    }

    void init(unique_ptr<pair<T,V>[]>& _table)
    {
        for (int i = 0; i < MAX_SIZE; ++i)
        {
            _table[i].first = EMPTY;
            _table[i].second = V();
        }
    }

    int MAX_SIZE = 1 << 5;
    int MASK = MAX_SIZE - 1;

    const int EMPTY = numeric_limits<T>::min();
    const int ERASED = numeric_limits<T>::min() + 1;

    unique_ptr<pair<T,V>[]> table;

    size_t _size;

    void insert(unique_ptr<pair<T,V>[]>& _table, const T& key, const V& value)
    {
        int p = (prime * key) & MASK;

        while (_table[p].first != key && _table[p].first != EMPTY && _table[p].first != ERASED)
            p = (p + 1) & MASK;

        _table[p].first = key;
        _table[p].second += value;
        _size++;
    }

    void erase(unique_ptr<pair<T,V>[]>& _table, const T& key)
    {
        int p = (prime * key) & MASK;

        while (_table[p].first != key && _table[p].first != EMPTY)
            p = (p + 1) & MASK;

        if (_table[p].first == key)
        {
            _table[p].first = ERASED;
            _table[p].second = V();
            _size--;
        }
    }

    V find(const unique_ptr<pair<T,V>[]>& _table, const T& key) const
    {
        int p = (prime * key) & MASK;

        while (_table[p].first != key && _table[p].first != EMPTY)
            p = (p + 1) & MASK;

        if (_table[p].first == key)
            return _table[p].second;
        else
            return V();
    }

    void rehash()
    {
        unique_ptr<pair<T,V>[]> _table(new pair<T,V>[2 * MAX_SIZE]);

        for (int i = 0; i < MAX_SIZE; ++i)
            if (table[i].first != ERASED && table[i].first != EMPTY)
                this->insert(_table, table[i].first, table[i].second);

        table = std::move(_table);
        MAX_SIZE *= 2;
        MASK = MAX_SIZE - 1;
    }

public:

    HashTable() : prime(generatePrime()), table(), _size(0)
    {
        static_assert(std::is_integral<T>::value, "Integer required.");
        table = make_unique<pair<T,V>[]>(MAX_SIZE);
        this->init(table);
    }

    void insert(const T& key, const V& value)
    {
        this->insert(table, key, value);

        if (70.0 * MAX_SIZE / 100.0 < _size)
            rehash();
    }

    void erase(const T& key)
    {
        this->erase(table, key);
    }

    V find(const T& key) const
    {
        return this->find(table, key);
    }
};

int main()
{
    ifstream in("hashuri.in");
    ofstream out("hashuri.out");

    HashTable<int,int> T;

    int N, X, tip;

    in >> N;

    while (N--)
    {
        in >> tip >> X;

        if (tip == 1)
            T.insert(X, 1);
        else if (tip == 2)
            T.erase(X);
        else
            out << (T.find(X) > 0) << "\n";
    }

    return 0;
}