#include <fstream>
#ifndef HASHTABLE_OPEN_ADDRESSING_LAZY_DELETION_H
#define HASHTABLE_OPEN_ADDRESSING_LAZY_DELETION_H
#include <iostream>
#include <vector>
#define ULL unsigned long long int
#define PRIME_CAPACITY_FOR_HASH 666013
enum SlotType {Empty, Occupied, Lazy_Delete};
template <typename Tkey, typename Tvalue>
struct info {
Tkey key;
Tvalue value;
};
template <typename Tkey, typename Tvalue>
class Hashtable_OALD {
private:
std::vector<struct info<Tkey, Tvalue>> hash_table_;
std::vector<SlotType> slot_;
int size_;
int capacity_;
ULL (*hash_)(Tkey);
public:
Hashtable_OALD(int capacity, ULL (*h)(Tkey));
~Hashtable_OALD();
int findSlotInsert(const Tkey&);
int findSlotSearch(const Tkey&);
bool lookup(const Tkey&);
void set(const Tkey&, const Tvalue&);
void remove(const Tkey&);
Tvalue operator[](const Tkey&);
int getSize();
int getCapacity();
void printHashTable();
};
template <typename Tkey, typename Tvalue>
Hashtable_OALD<Tkey, Tvalue>::Hashtable_OALD(int capacity, ULL (*h)(Tkey)):
hash_table_(capacity), slot_(capacity, SlotType::Empty),
size_(0), capacity_(capacity), hash_(h) {}
template <typename Tkey, typename Tvalue>
Hashtable_OALD<Tkey, Tvalue>::~Hashtable_OALD() {}
template <typename Tkey, typename Tvalue>
int Hashtable_OALD<Tkey, Tvalue>::findSlotInsert(const Tkey& key) {
int i = hash_(key) % capacity_;
// search until we either find the key, or find an empty slot.
while (slot_[i] == SlotType::Occupied && hash_table_[i].key != key) {
i = (i + 1) % capacity_;
}
// Cases found: Empty slot, Lazy_Delete slot, slot[i].key == key
return i;
}
template <typename Tkey, typename Tvalue>
int Hashtable_OALD<Tkey, Tvalue>::findSlotSearch(const Tkey& key) {
int i = hash_(key) % capacity_;
// search until we either find the key, or find an empty slot.
while (slot_[i] != SlotType::Empty && hash_table_[i].key != key) {
i = (i + 1) % capacity_;
}
// Cases found: Empty slot (passed all Occupied and Lazy_Delet slots), slot[i].key == key
return i;
}
template <typename Tkey, typename Tvalue>
bool Hashtable_OALD<Tkey, Tvalue>::lookup(const Tkey& key) {
int i = findSlotSearch(key);
if (slot_[i] == SlotType::Occupied) { // key is in table
return true;
}
else { // key is not in table
return false;
}
}
template <typename Tkey, typename Tvalue>
void Hashtable_OALD<Tkey, Tvalue>::set(const Tkey& key, const Tvalue& value) {
int i = findSlotInsert(key);
hash_table_[i].key = key;
hash_table_[i].value = value;
slot_[i] = SlotType::Occupied;
}
template <typename Tkey, typename Tvalue>
void Hashtable_OALD<Tkey, Tvalue>::remove(const Tkey& key) {
int i = findSlotInsert(key);
if (slot_[i] == SlotType::Occupied) { // key is in the table
slot_[i] = SlotType::Lazy_Delete;
}
}
template <typename Tkey, typename Tvalue>
Tvalue Hashtable_OALD<Tkey, Tvalue>::operator[](const Tkey& key) {
int i = findSlotSearch(key);
if (slot_[i] == SlotType::Occupied) { // key is in table
return hash_table_[i].value;
}
else { // key is not in table
return Tvalue();
}
}
template <typename Tkey, typename Tvalue>
int Hashtable_OALD<Tkey, Tvalue>::getSize() {
return size_;
}
template <typename Tkey, typename Tvalue>
int Hashtable_OALD<Tkey, Tvalue>::getCapacity() {
return capacity_;
}
template <typename Tkey, typename Tvalue>
void Hashtable_OALD<Tkey, Tvalue>::printHashTable() {
for (unsigned int i = 0; i < hash_table_.size(); ++i) {
if (slot_[i] == SlotType::Occupied) {
std::cout << "<" << i << ", " << hash_table_[i].key << ", " << hash_table_[i].value << "> ";
}
}
std::cout << '\n';
for (unsigned int i = 0; i < slot_.size(); ++i) {
std::cout << slot_[i] << ' ';
}
std::cout << "\n\n";
}
#endif // HASHTABLE_OPEN_ADDRESSING_LAZY_DELETION_H
unsigned long long int try_hash(int number) {
return number;
}
int main() {
std::ifstream fin("hashuri.in");
std::ofstream fout("hashuri.out");
Hashtable_OALD<int, int> ht(PRIME_CAPACITY_FOR_HASH, try_hash);
int N, q, x;
fin >> N;
for (int i = 0; i < N; ++i) {
fin >> q >> x;
switch(q) {
case 1:
ht.set(x, 1);
break;
case 2:
ht.remove(x);
break;
default:
fout << ht.lookup(x) << '\n';
}
}
fin.close();
fout.close();
return 0;
}