Cod sursa(job #910778)
#include <iostream>
#include <fstream>
#include <algorithm>
#include <tr1/functional>
template<class DataType>
class HashSet {
public:
HashSet(const size_t &bits = 4) {
Initialize(1 << bits);
}
~HashSet() {
delete[] data_;
delete[] data_type_;
}
class Iterator : public std::iterator<std::input_iterator_tag, DataType> {
public:
Iterator(DataType* const data, char* const data_type):
data_(data),
data_type_(data_type) {
}
Iterator(const Iterator& that):
data_(that.data_),
data_type_(that.data_type_) {
}
bool Empty() const {
return *data_type_ == kEmptyElement;
}
bool Filled() const {
return *data_type_ == kFilledElement;
}
Iterator& operator=(const DataType& that) {
*data_ = that;
*data_type_ = kFilledElement;
return *this;
}
bool operator!=(const Iterator& that) const {
return data_ != that.data_ || data_type_ != that.data_type_;
}
bool operator!=(const DataType& that) const {
return *data_ != that;
}
bool operator==(const DataType& that) const {
return *data_ == that;
}
const DataType& operator*() const {
return *data_;
}
private:
enum {
kEmptyElement = 0,
kErasedElement = 1,
kFilledElement = 2,
};
friend class HashSet;
DataType *data_;
char *data_type_;
};
Iterator Find(const DataType& data) {
Iterator it = PointTo(data);
while (!it.Empty() && it != data)
it = PointToNext(it);
if (it.Empty())
return End();
return it;
}
std::pair<Iterator, bool> Insert(const DataType& element) {
Iterator it = Find(element);
if (it != End())
return std::pair<Iterator, bool>(it, false);
it = PointTo(element);
while (it.Filled()) {
it = PointToNext(it);
}
if (it.Empty())
++non_empty_elements_;
it = element;
if (non_empty_elements_ == maximum_capacity_) {
Grow();
return std::pair<Iterator, bool>(Find(element), true);
}
return std::pair<Iterator, bool>(it, true);
}
template<class InputIterator>
size_t Insert(InputIterator first, InputIterator last) {
size_t inserted = 0;
while (first != last) {
if (Insert(*first).second)
++inserted;
}
return inserted;
}
bool Erase(const DataType& element) {
Iterator it = Find(element);
if (it != End()) {
Erase(it);
return true;
}
return false;
}
bool Erase(const Iterator& iterator) {
*(iterator.data_) = DataType();
*(iterator.data_type_) = kErasedElement;
filled_elements_--;
return true;
}
Iterator Begin() {
return Iterator(data_, data_type_);
}
Iterator End() {
return Iterator(data_ + size_, data_type_ + size_);
}
private:
enum {
kEmptyElement = 0,
kErasedElement = 1,
kFilledElement = 2,
};
static const double kLoadFactor;
static const std::tr1::hash<DataType> kHashFunction;
void Initialize(const int &size) {
size_ = size;
maximum_capacity_ = kLoadFactor * size;
non_empty_elements_ = 0;
filled_elements_ = 0;
data_ = new DataType[size];
data_type_ = new char[size];
std::fill_n(data_type_, size, kEmptyElement);
}
Iterator PointTo(const DataType& data) {
size_t position = kHashFunction(data);
return Iterator(data_ + position, data_type_ + position);
}
Iterator PointToNext(const Iterator& current) {
size_t position = current.data_ - data_;
position = (position * 5 + 1) & (size_ - 1);
return Iterator(data_ + position, data_type_ + position);
}
void Grow() {
DataType *old_data = data_;
char* old_data_type = data_type_;
Iterator old_begin = Begin(), old_end = End();
Initialize(size_ * 2);
Insert(old_begin, old_end);
delete[] old_data;
delete[] old_data_type;
}
size_t size_;
size_t maximum_capacity_;
size_t non_empty_elements_;
size_t filled_elements_;
DataType *data_;
// FIXME: we are now using 8 bits for information for which we only need 2 bits, optimize a little
char *data_type_;
};
template<class DataType>
const double HashSet<DataType>::kLoadFactor = 0.75;
template<class DataType>
const std::tr1::hash<DataType> HashSet<DataType>::kHashFunction;
using namespace std;
int main() {
ifstream cin("hashuri.in");
ofstream cout("hashuri.out");
int N; cin >> N;
HashSet<int> H;
for (int i = 0; i < N; ++i) {
int type, value;
cin >> type>> value;
if (type == 1)
H.Insert(value);
if (type == 2)
H.Erase(value);
if (type == 3)
cout << bool(H.Find(value) != H.End()) << "\n";
}
}