Cod sursa(job #3325563)

Utilizator Razvan23Razvan Mosanu Razvan23 Data 25 noiembrie 2025 19:14:05
Problema Hashuri Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.07 kb
#include <bits/stdc++.h>
using namespace std;

ifstream fin("hashuri.in");
ofstream fout("hashuri.out");

// --- 1. FUNCTII DE HASH (Ramane neschimbat, e perfect) ---
template <typename T>
struct HashFunction {
    int operator()(const T& key, int N) const { return 0; }
};

template <>
struct HashFunction<int> {
    long long splitmix64(long long x) const {
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }
    int operator()(const int& x, int N) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return (splitmix64(x + FIXED_RANDOM) % N + N) % N;
    }
};

// --- 2. CLASA HASH CU VECTOR DE VECTORI ---
template <typename T>
class Hash {
public:
    int n;
    // H[index] contine un vector de perechi {valoare, frecventa}
    // Nu mai folosim pointeri (*H), ci obiectul direct.
    vector<vector<pair<T, int>>> H;
    HashFunction<T> hasher;

    // Constructor
    Hash(int _n = (1<<16) - 1) : n(_n)
    {
        H.resize(n);
    }

    // Nu mai avem nevoie de Destructor (~Hash), vectorul se curata singur!

    void Insert(T x) {
        int index = hasher(x, n);

        // Cautam in bucket-ul corespunzator
        // Folosim referinta (&) ca sa putem modifica frecventa direct
        for (auto &elem : H[index]) {
            if (elem.first == x) {
                elem.second++; // Exista, crestem frecventa
                return;
            }
        }

        // Daca nu exista, adaugam la final cu frecventa 1
        H[index].push_back({x, 1});
    }

    void Delete(T x) {
        int index = hasher(x, n);
        for (size_t i = 0; i < H[index].size(); i++) {
            if (H[index][i].first == x) {
                H[index][i].second--; // Scad frecventa

                // Daca frecventa a ajuns la 0, stergem fizic elementul
                if (H[index][i].second == 0) {
                    // Swap cu ultimul element si Pop Back (O(1))
                    H[index][i] = H[index].back();
                    H[index].pop_back();
                }
                return;
            }
        }
    }

    int Count(T x) {
        int index = hasher(x, n);
        for (const auto &elem : H[index]) {
            if (elem.first == x) return elem.second;
        }
        return 0;
    }

    bool Find(T x) {
        return Count(x) > 0;
    }
};

// --- 3. REZOLVAREA PROBLEMEI ---
class Hashuri : public Hash<int>
{
public:
    Hashuri() : Hash<int>((1<<10) - 1) { }

    void Rezolvare() {
        int op, n_ops, x;
        fin >> n_ops;
        while(n_ops--) {
            fin >> op >> x;
            if (op == 1) Insert(x);
            else if (op == 2) Delete(x);
            else fout << Find(x) << "\n";
        }
    }
};

int main() {
    ios_base::sync_with_stdio(0);
    fin.tie(0);
    fout.tie(0);

    Hashuri A;
    A.Rezolvare();

    fin.close();
    fout.close();
    return 0;
}