Pagini recente » Soluţii ONIS 2015, Runda 2 | Cod sursa (job #183889) | Cod sursa (job #553485) | Istoria paginii runda/simulare_preoni_ig/clasament | Cod sursa (job #1569117)
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <sstream>
#include <atomic>
using namespace std;
//bool compareAndSwap64(volatile long long int *value, long long int expected, long long int newValue);
//bool compareAndSwap(volatile long int *value, long int expected, long int newValue);
long long int compareAndSwap64Old(volatile long long int *value, long long int expected, long long int newValue) {
if (*value == expected) {
*value = newValue;
return expected;
}
return *value;
}
//long int compareAndSwapOld(volatile long int *value, long int expected, long int newValue);
//void store64(volatile long long int *destination, long long int source);
void store(volatile long int *destination, long int source) {
*destination = source;
}
//long long int fetchAndIncrement64(volatile long long int *value);
long int fetchAndIncrement(volatile long int *value) {
(*value)++;
return (*value) - 1;
}
template <typename ValueType>
struct HT {
struct E {
unsigned long long int Key;
long int Value;
E() {
Key = 0LL;
Value = 0;
}
};
std::vector <ValueType> _values;
std::vector <E> _table;
long int _valueIndex;
unsigned int _mask;
HT(unsigned int N) {
//Indexing starts from 1 because 0 is a deleted sync
_valueIndex = 1;
unsigned int n = N;
while (n & (n + 1)) {
n |= (n + 1);
}
// Make it bigger for sparser collisions
// minimum 65k elements will need to 255k buckets
// with 90% access of first time hash, 99% second next bucket...
n |= (n + 1);
_table.resize(size_t(n) + 1);
// The value found on position 0 is special and it means it doesn't exist.
_values.resize(N + 1);
_mask = n;
}
inline static unsigned long int hash(unsigned long long int h) {
h ^= h >> 33;
h *= 0xff51afd7ed558ccd;
h ^= h >> 33;
h *= 0xc4ceb9fe1a85ec53;
h ^= h >> 33;
return static_cast<unsigned long int>(h);
}
ValueType *operator[](unsigned long long int key) {
auto h = hash(key);
// Table must not be full, otherwise this algorithm
// will not end
while (true) {
h = h & _mask;
if (_table[h].Key == 0) {
return nullptr;
}
else if (_table[h].Key == key) {
volatile auto vindex = _table[h].Value;
if (vindex > 0) {
return _values[static_cast<unsigned int>(vindex)];
}
return nullptr;
}
h++;
}
}
bool contains(unsigned long long int key) {
auto h = hash(key);
// Table must not be full, otherwise this algorithm
// will not end
while (true) {
h = h & _mask;
if (_table[h].Key == 0) {
return false;
}
else if (_table[h].Key == key && _table[h].Value > 0) {
return true;
}
h++;
}
}
void insert(unsigned long long int key, ValueType const &value) {
auto h = hash(key);
while (true) {
// Table must not be full, otherwise this algorithm
// will not end
h = h & _mask;
// Make sure that we write the key into an empty slot atomically.
auto kv = static_cast<unsigned long long int>(compareAndSwap64Old(
reinterpret_cast<volatile long long int*>(&_table[h].Key), 0LL, static_cast<long long int>(key)));
/* Atomic initialize */
if (kv == 0) {
// This code is guaranteed to be executed only once for each bucket.
auto volatile vindex = fetchAndIncrement(reinterpret_cast<volatile long int*>(&_valueIndex));
store(reinterpret_cast<volatile long int*>(&_table[h].Value), vindex);
}
// We must be very careful here because someone else might want to either:
// 1. Insert and override the same key
// 2. Delete the key.
// If someone tries to insert here before vindex will be != 0 it's fine because we
// simply don't write the value. If someone tries to delete while being here
// we have to simply *undelete by setting the sign positive for vIndex.
// race conditions may happen if we insert/delete on the same key (as we expect).
if (kv == 0LL || kv == key) {
auto volatile vindex = static_cast<long int>(_table[h].Value);
if (vindex < 0) {
vindex = -vindex;
// Deleted values are undeleted
store(reinterpret_cast<volatile long int*>(&_table[h].Value), vindex);
}
_values[static_cast<unsigned int>(vindex)] = value;
return;
}
h++;
}
}
void remove(unsigned long long int key) {
auto h = hash(key);
while (true) {
h = h & _mask;
// We didn't find the element.
if (_table[h].Key == 0) {
return;
}
// If the key matches we set the state to
// deleted by making the index negative
else if (_table[h].Key == key) {
auto volatile vindex = _table[h].Value;
if (vindex > 0) {
vindex = -vindex;
store(reinterpret_cast<volatile long int*>(&_table[h].Value), vindex);
}
return;
}
h++;
}
}
};
int main() {
FILE *out = fopen("hashuri.out", "w");
FILE *in = fopen("hashuri.in", "r");
int n;
fscanf(in, "%d", &n);
HT<bool> ht(n);
for (int i = 0; i < n; i++) {
unsigned long long int op, c;
fscanf(in, "%llu%llu", &op, &c);
if (op == 1) {
ht.insert(c, true);
}
else if (op == 2) {
ht.remove(c);
}
else if (op == 3) {
if (ht.contains(c))
fprintf(out, "1\n");
else
fprintf(out, "0\n");
}
}
return 0;
}