#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;
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+IHF1ZXJpZXMobik7CgkKCWZvciAoYXV0byYgaXQgOiBxdWVyaWVzKSB7CgkJaXQgPSBzdGQ6Om1ha2VfcGFpcihzdGQ6OnJhbmQoKSAlIChpbnQpMWU5LCByYW5kX3VsbCgpKTsKCX0KCQoJZG91YmxlIHQgPSBjbG9jaygpOwoJCglzdGQ6OnVub3JkZXJlZF9zZXQ8SGFzaCwgZ2V0SGFzaD4gaGFzaHRhYmxlOwoJCglmb3IgKGF1dG8gaXQgOiBhcnJheSkgewoJCWhhc2h0YWJsZS5pbnNlcnQoaXQpOwoJfQoJCglpbnQgY291bnQxID0gMDsKCQoJZm9yIChhdXRvIGhhc2ggOiBxdWVyaWVzKSB7CgkJY291bnQxICs9IGhhc2h0YWJsZS5maW5kKGhhc2gpICE9IGhhc2h0YWJsZS5lbmQoKTsKCX0KCQoJZG91YmxlIHRpbWUxID0gKGNsb2NrKCkgLSB0KSAvIENMT0NLU19QRVJfU0VDOwoJCgl0ID0gY2xvY2soKTsKCQoJc3RkOjpzb3J0KGFycmF5LmJlZ2luKCksIGFycmF5LmVuZCgpKTsKCQoJaW50IGNvdW50MiA9IDA7CgkKCWZvciAoYXV0byBoYXNoIDogcXVlcmllcykgewoJCWNvdW50MiArPSBzdGQ6OmJpbmFyeV9zZWFyY2goYXJyYXkuYmVnaW4oKSwgYXJyYXkuZW5kKCksIGhhc2gpOwoJfQoJCglkb3VibGUgdGltZTIgPSAoY2xvY2soKSAtIHQpIC8gQ0xPQ0tTX1BFUl9TRUM7CgkKCWFzc2VydChjb3VudDEgPT0gY291bnQyKTsKCQoJZnByaW50ZihzdGRvdXQsICJzaXplICYgcXVlcmllcyA9ICVkXG4iLCBuKTsKCWZwcmludGYoc3Rkb3V0LCAiICAgICBoYXNodGFibGUgPSAlMC4zZnNcbiIsIHRpbWUxKTsKCWZwcmludGYoc3Rkb3V0LCAic29ydCtiaW5zZWFyY2ggPSAlMC4zZnNcbiIsIHRpbWUyKTsKCQoJcmV0dXJuIDA7Cn0=