#include <iostream>
#include <algorithm>
#include <vector>
#include <unordered_set>
#include <cstdlib>
#include <ctime>
#include <cassert>
typedef unsigned long long ull;
typedef std::pair<int,ull> Hash;
struct getHash {
public:
template <typename T, typename U>
std::size_t operator()(const std::pair<T, U> &x) const
{
return std::hash<T>()(x.first) ^ std::hash<U>()(x.second);
}
};
ull rand_ull() {
ull res = 0;
for (int i = 0; i < 6; ++i) {
(res *= 1000) += (std::rand() % 1000);
}
return res;
}
int main() {
std::srand(std::time(0));
const int n = (int)4e6;
std::vector<Hash> array(n);
for (auto& it : array) {
it = std::make_pair(std::rand() % (int)1e9, rand_ull());
}
std::vector<Hash> queries(n);
for (auto& it : queries) {
it = std::make_pair(std::rand() % (int)1e9, rand_ull());
}
double t = clock();
std::unordered_set<Hash, getHash> hashtable; hashtable.max_load_factor(0.247);
for (auto it : array) {
hashtable.insert(it);
}
int count1 = 0;
for (auto hash : queries) {
count1 += hashtable.find(hash) != hashtable.end();
}
double time1 = (clock() - t) / CLOCKS_PER_SEC;
t = clock();
std::sort(array.begin(), array.end());
int count2 = 0;
for (auto hash : queries) {
count2 += std::binary_search(array.begin(), array.end(), hash);
}
double time2 = (clock() - t) / CLOCKS_PER_SEC;
assert(count1 == count2);
fprintf(stdout, "size & queries = %d\n", n);
fprintf(stdout, " hashtable = %0.3fs\n", time1);
fprintf(stdout, "sort+binsearch = %0.3fs\n", time2);
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8YWxnb3JpdGhtPgojaW5jbHVkZSA8dmVjdG9yPgojaW5jbHVkZSA8dW5vcmRlcmVkX3NldD4KI2luY2x1ZGUgPGNzdGRsaWI+CiNpbmNsdWRlIDxjdGltZT4KI2luY2x1ZGUgPGNhc3NlcnQ+Cgp0eXBlZGVmIHVuc2lnbmVkIGxvbmcgbG9uZyB1bGw7CnR5cGVkZWYgc3RkOjpwYWlyPGludCx1bGw+IEhhc2g7CgpzdHJ1Y3QgZ2V0SGFzaCB7CnB1YmxpYzoKCXRlbXBsYXRlIDx0eXBlbmFtZSBULCB0eXBlbmFtZSBVPgoJc3RkOjpzaXplX3Qgb3BlcmF0b3IoKShjb25zdCBzdGQ6OnBhaXI8VCwgVT4gJngpIGNvbnN0Cgl7CgkJcmV0dXJuIHN0ZDo6aGFzaDxUPigpKHguZmlyc3QpIF4gc3RkOjpoYXNoPFU+KCkoeC5zZWNvbmQpOwoJfQp9OwoKdWxsIHJhbmRfdWxsKCkgewoJdWxsIHJlcyA9IDA7Cglmb3IgKGludCBpID0gMDsgaSA8IDY7ICsraSkgewoJCShyZXMgKj0gMTAwMCkgKz0gKHN0ZDo6cmFuZCgpICUgMTAwMCk7Cgl9CglyZXR1cm4gcmVzOwp9CgppbnQgbWFpbigpIHsKCXN0ZDo6c3JhbmQoc3RkOjp0aW1lKDApKTsKCQoJY29uc3QgaW50IG4gPSAoaW50KTRlNjsKCQoJc3RkOjp2ZWN0b3I8SGFzaD4gYXJyYXkobik7CgkKCWZvciAoYXV0byYgaXQgOiBhcnJheSkgewoJCWl0ID0gc3RkOjptYWtlX3BhaXIoc3RkOjpyYW5kKCkgJSAoaW50KTFlOSwgcmFuZF91bGwoKSk7Cgl9CgkKCXN0ZDo6dmVjdG9yPEhhc2g+IHF1ZXJpZXMobik7CgkKCWZvciAoYXV0byYgaXQgOiBxdWVyaWVzKSB7CgkJaXQgPSBzdGQ6Om1ha2VfcGFpcihzdGQ6OnJhbmQoKSAlIChpbnQpMWU5LCByYW5kX3VsbCgpKTsKCX0KCQoJZG91YmxlIHQgPSBjbG9jaygpOwoJCglzdGQ6OnVub3JkZXJlZF9zZXQ8SGFzaCwgZ2V0SGFzaD4gaGFzaHRhYmxlOyBoYXNodGFibGUubWF4X2xvYWRfZmFjdG9yKDAuMjQ3KTsKCQoJZm9yIChhdXRvIGl0IDogYXJyYXkpIHsKCQloYXNodGFibGUuaW5zZXJ0KGl0KTsKCX0KCQoJaW50IGNvdW50MSA9IDA7CgkKCWZvciAoYXV0byBoYXNoIDogcXVlcmllcykgewoJCWNvdW50MSArPSBoYXNodGFibGUuZmluZChoYXNoKSAhPSBoYXNodGFibGUuZW5kKCk7Cgl9CgkKCWRvdWJsZSB0aW1lMSA9IChjbG9jaygpIC0gdCkgLyBDTE9DS1NfUEVSX1NFQzsKCQoJdCA9IGNsb2NrKCk7CgkKCXN0ZDo6c29ydChhcnJheS5iZWdpbigpLCBhcnJheS5lbmQoKSk7CgkKCWludCBjb3VudDIgPSAwOwoJCglmb3IgKGF1dG8gaGFzaCA6IHF1ZXJpZXMpIHsKCQljb3VudDIgKz0gc3RkOjpiaW5hcnlfc2VhcmNoKGFycmF5LmJlZ2luKCksIGFycmF5LmVuZCgpLCBoYXNoKTsKCX0KCQoJZG91YmxlIHRpbWUyID0gKGNsb2NrKCkgLSB0KSAvIENMT0NLU19QRVJfU0VDOwoJCglhc3NlcnQoY291bnQxID09IGNvdW50Mik7CgkKCWZwcmludGYoc3Rkb3V0LCAic2l6ZSAmIHF1ZXJpZXMgPSAlZFxuIiwgbik7CglmcHJpbnRmKHN0ZG91dCwgIiAgICAgaGFzaHRhYmxlID0gJTAuM2ZzXG4iLCB0aW1lMSk7CglmcHJpbnRmKHN0ZG91dCwgInNvcnQrYmluc2VhcmNoID0gJTAuM2ZzXG4iLCB0aW1lMik7CgkKCXJldHVybiAwOwp9