Pagini recente » Profil LeonGS | Cod sursa (job #910439) | Cod sursa (job #2391497) | Cod sursa (job #2576743) | Cod sursa (job #2872087)
//#include <iostream>
//#include <cstdlib>
//#include <fstream>
//
//using namespace std;
//
//ifstream in("hashuri.in");
//ofstream out("hashuri.out");
//
//const int p = 1500041;
//const int m = 668611;
//
//long long int a1, b1;
//
//int calculate_hash_function_1(long long int x) {
// return ((long long)(a1 * x + b1) % p) % m;
//}
//
//long long int a2, b2;
//
//int calculate_hash_function_2(long long int x) {
// return ((long long )(a2 * x + b2) % p) % m;
//}
//
//long long int T1[m], T2[m];
//
//bool Search(long long int x) {
// return (T1[calculate_hash_function_1(x)] == x || T2[calculate_hash_function_2(x)] == x);
//}
//
//void Insert(long long int x) {
// long long int y, z;
// int h1 = calculate_hash_function_1(x);
// if (T1[h1] == 0 || T1[h1] == x) {
// T1[h1] = x;
// return;
// } else {
// y = T1[h1];
// T1[h1] = x;
// }
// int h2 = calculate_hash_function_2(y);
// if (T2[h2] == 0 || T2[h2] == y) {
// T2[h2] = y;
// return;
// } else {
// z = T2[h2];
// T2[h2] = y;
// }
// Insert(z);
//}
//
//void Delete(long long int x) {
// int h1 = calculate_hash_function_1(x);
// int h2 = calculate_hash_function_2(x);
// if (T1[h1] == x) {
// T1[h1] = 0;
// }
// if (T2[h1] == x) {
// T2[h2] = 0;
// }
//}
//
//int main() {
//
// srand(time(nullptr));
// a1 = rand()%p;
// b1 = rand()%p;
// a2 = rand()%p;
// b2 = rand()%p;
//
// long long int n, op, x;
// in >> n;
// while (n--) {
// in >> op >> x;
// if (op == 1) {
// Insert(x);
// } else if (op == 2) {
// Delete(x);
// } else {
// out << Search(x) << "\n";
// }
// }
//
//
// return 0;
//}
#include <iostream>
#include <cmath>
#include <fstream>
#include <vector>
using namespace std;
ifstream in("hashuri.in");
ofstream out("hashuri.out");
class MyHashMap {
public:
/** Initialize your data structure here. */
MyHashMap() {
}
/** value will always be non-negative. */
void put(int key, int value) {
//if incdeces hash1[key] or hash2[key] contains needed key, then we can just update value
//else we need to push any key out
auto h1 = hash1(key), h2 = hash2(key);
if (buffer_[h1].first == key)
buffer_[h1].second = value;
else if (buffer_[h2].first == key)
buffer_[h2].second = value;
else
push(key, value);
}
/** Returns the value to which the specified key is mapped, or -1 if this map contains no mapping for the key */
int get(int key) {
//Main feature of cuckoo hashing -- just check two positions
auto h1 = hash1(key), h2 = hash2(key);
if (buffer_[h1].first == key)
return buffer_[h1].second;
if (buffer_[h2].first == key)
return buffer_[h2].second;
return -1;
}
/** Removes the mapping of the specified value key if this map contains a mapping for the key */
void remove(int key) {
auto h1 = hash1(key), h2 = hash2(key);
if (buffer_[h1].first == key){
buffer_[h1] = EMPTY;
--count_;
}
else if (buffer_[h2].first == key){
buffer_[h2] = EMPTY;
--count_;
}
}
private:
size_t hash(int hash_param, int key) const {
//arbitrary family of hash functions. hash_param determines the instance of hash function
return std::hash<int>()(key) / hash_param % (buffer_.size() / 2);
}
size_t hash1(int key) const { return hash(hash1_, key); }
size_t hash2(int key) const { return hash(hash2_, key) + buffer_.size() / 2; }
void push(int key, int value){
++count_;
//to control load factor
if (count_ >= buffer_.size() / 4)
resize();
//switch for changing hash functions.
//if we used i2 = hash1(k1) previously and pushed out some other key k2: i2 = hash1(k2),
//we have to use other hash i2' = hash2(k2) to find a new place for k2.
bool switcher = true;
for (size_t i = 0; i < limit_; ++i) {
auto h1 = hash1(key), h2 = hash2(key);
if (buffer_[h1] == EMPTY){
buffer_[h1] = {key, value};
break;
}
if (buffer_[h2] == EMPTY){
buffer_[h2] = {key, value};
break;
}
auto h = switcher ? h1 : h2;
std::swap(key, buffer_[h].first);
std::swap(value, buffer_[h].second);
switcher = !switcher;
//If we gonna exceed the limit, we can rehash current map with new hash functions.
//Note, we can try to do it without resizing.
//After that we should insert current pushed out key to the new place.
if (i + 1 == limit_){
rehash();
i = static_cast<size_t>(-1);
}
}
}
void rehash(){
//Defining new hash functions is hard so I used simple ones.
//First hash function I left static.
hash1_ = 1;
hash2_ = rand() % limit_ + 1;
//Durty hack. We gonna rehash elements. We can do it inplace with `put` function.
//But we have to change limit_ variable to the number of elements during rehashing.
auto real_limit = limit_;
limit_ = count_;
for (size_t i = 0; i < buffer_.size(); ++i){
if (buffer_[i] != EMPTY && hash1(buffer_[i].first) != i && hash2(buffer_[i].first) != i){
auto p = buffer_[i];
buffer_[i] = EMPTY;
put(p.first, p.second);
}
}
limit_ = real_limit;
}
void resize(){
//limit parameter can be tuned. It seems to be ok if limit is a*log2(N).
buffer_.resize(buffer_.size() * 2, EMPTY);
limit_ = 40 * static_cast<int>(std::log2(buffer_.size()));
rehash();
}
//number of elements
size_t count_ = 0;
//current max number of cuckoo pushing
int limit_ = 2;
//parameters of hash functions
int hash1_ = 1, hash2_ = 2;
//buffer with parameters {key, value}
const std::pair<int, int> EMPTY = {-1, -1};
std::vector<std::pair<int,int> > buffer_ = std::vector<std::pair<int,int> >(2, EMPTY);
};
/**
* Your MyHashMap object will be instantiated and called as such:
* MyHashMap* obj = new MyHashMap();
* obj->put(key,value);
* int param_2 = obj->get(key);
* obj->remove(key);
*/
int main() {
MyHashMap* obj = new MyHashMap();
long long int n, op, x;
in >> n;
while (n--) {
in >> op >> x;
if (op == 1) {
obj->put(x, 0);
} else if (op == 2) {
obj->remove(x);
} else {
out << obj->get(x) + 1 << "\n";
}
}
return 0;
}