Pagini recente » Cod sursa (job #27983) | Cod sursa (job #3353528) | Cod sursa (job #207258) | Cod sursa (job #719913) | Cod sursa (job #3325565)
#include <bits/stdc++.h>
using namespace std;
ifstream fin("hashuri.in");
ofstream fout("hashuri.out");
// CONSTANTE
const int N_HASH = 666013; // Dimensiunea tabelei (Numar prim)
const int MAX_OPS = 200005; // Numarul maxim de inserari (din enuntul problemei)
// MEMORIE STATICA (Alocata in segmentul de date, nu pe heap)
// head[h] = indexul primului element din bucket-ul h
int head[N_HASH];
// Acestea simuleaza nodurile: valoare si pointerul 'next'
int val[MAX_OPS];
int urm[MAX_OPS];
int pos = 1; // Cursorul pentru alocare (incepem de la 1, 0 inseamna NULL)
// Functia de Hash (Pastram SplitMix64 pentru siguranta)
struct CustomHash {
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()(int x) const {
// Hardcodat random pentru viteza maxima (evitam chrono la fiecare apel)
return (splitmix64(x + 0x9e3779b9) % N_HASH + N_HASH) % N_HASH;
}
} hasher;
class FastHash {
public:
void Insert(int x) {
int h = hasher(x);
// Verificam daca exista deja (optional, depinde de problema)
for (int p = head[h]; p != 0; p = urm[p]) {
if (val[p] == x) return;
}
// Inseram la INCEPUTUL listei (O(1) pur)
// 1. Punem valoarea in pozitia curenta libera
val[pos] = x;
// 2. Legam noul nod de vechiul 'head' al bucket-ului
urm[pos] = head[h];
// 3. Noul nod devine 'head'
head[h] = pos;
// 4. Avansam cursorul pentru urmatoarea inserare
pos++;
}
void Delete(int x) {
int h = hasher(x);
// Trebuie sa tinem minte nodul anterior pentru a reface legaturile
int p = head[h];
int ant = 0; // 0 inseamna null/nimic
while (p != 0) {
if (val[p] == x) {
if (ant == 0) {
// Stergem primul element: Head-ul devine urmatorul
head[h] = urm[p];
} else {
// Stergem element din interior: Anteriorul sare peste 'p'
urm[ant] = urm[p];
}
// Nu "eliberam" memoria la pos, o lasam "pierduta".
// In concursuri memoria e ieftina, timpul e scump.
return;
}
ant = p;
p = urm[p];
}
}
bool Find(int x) {
int h = hasher(x);
// Parcurgem lista folosind indici in loc de pointeri
for (int p = head[h]; p != 0; p = urm[p]) {
if (val[p] == x) return true;
}
return false;
}
};
int main() {
// Optimizari I/O standard
ios_base::sync_with_stdio(0);
fin.tie(0);
fout.tie(0);
// Nu mai trebuie instantiata clasa daca e totul static/global,
// dar folosim un obiect wrapper pentru curatenie.
FastHash A;
int n, op, x;
fin >> n;
while(n--) {
fin >> op >> x;
if (op == 1) A.Insert(x);
else if (op == 2) A.Delete(x);
else fout << A.Find(x) << "\n";
}
return 0;
}