#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
uint32_t xorshift32(uint32_t x) {
x ^= x << 13;
x ^= x >> 17;
return x ^= x << 5;
}
using namespace std;
const int n = (1<<20);
const int block_size = 16;
alignas(64) int a[n], b[n+1];
int eytzinger(int i = 0, int k = 1) {
if (k <= n) {
i = eytzinger(i, 2 * k);
b[k] = a[i++];
i = eytzinger(i, 2 * k + 1);
}
return i;
}
int search(int x) {
int k = 1;
while (k <= n) {
__builtin_prefetch(b + k * block_size);
k = 2 * k + (b[k] < x);
}
k >>= __builtin_ffs(~k);
return k;
}
int main() {
std::cout << std::fixed << std::setprecision(3);
for (int i = 0; i < n; i++) {
a[i] = i;
}
eytzinger();
{
double tin = (double)clock();
int x = 1, check = 0;
for (int i = 0; i < (1 << 20); i++) {
x = xorshift32(x);
check ^= search(x);
}
double tout = (double)clock();
std::cout << "eytzinger = " << (tout - tin) / CLOCKS_PER_SEC << "s, check = " << check << std::endl;
}
{
double tin = (double)clock();
int x = 1, check = 0;
for (int i = 0; i < (1 << 20); i++) {
x = xorshift32(x);
check ^= int(std::lower_bound(a,a+n,x)-a);
}
double tout = (double)clock();
std::cout << "lower_bound = " << (tout - tin) / CLOCKS_PER_SEC << "s, check = " << check << std::endl;
}
return 0;
}
I3ByYWdtYSBHQ0Mgb3B0aW1pemUoIk9mYXN0IikKI2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+Cgp1aW50MzJfdCB4b3JzaGlmdDMyKHVpbnQzMl90IHgpIHsKCXggXj0geCA8PCAxMzsKCXggXj0geCA+PiAxNzsKCXJldHVybiB4IF49IHggPDwgNTsKfQoKdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCmNvbnN0IGludCBuID0gKDE8PDIwKTsKY29uc3QgaW50IGJsb2NrX3NpemUgPSAxNjsKYWxpZ25hcyg2NCkgaW50IGFbbl0sIGJbbisxXTsKCmludCBleXR6aW5nZXIoaW50IGkgPSAwLCBpbnQgayA9IDEpIHsKICAgIGlmIChrIDw9IG4pIHsKICAgICAgICBpID0gZXl0emluZ2VyKGksIDIgKiBrKTsKICAgICAgICBiW2tdID0gYVtpKytdOwogICAgICAgIGkgPSBleXR6aW5nZXIoaSwgMiAqIGsgKyAxKTsKICAgIH0KICAgIHJldHVybiBpOwp9CgppbnQgc2VhcmNoKGludCB4KSB7CiAgICBpbnQgayA9IDE7CiAgICB3aGlsZSAoayA8PSBuKSB7CiAgICAgICAgX19idWlsdGluX3ByZWZldGNoKGIgKyBrICogYmxvY2tfc2l6ZSk7CiAgICAgICAgayA9IDIgKiBrICsgKGJba10gPCB4KTsKICAgIH0KICAgIGsgPj49IF9fYnVpbHRpbl9mZnMofmspOwogICAgcmV0dXJuIGs7Cn0KCmludCBtYWluKCkgewoJc3RkOjpjb3V0IDw8IHN0ZDo6Zml4ZWQgPDwgc3RkOjpzZXRwcmVjaXNpb24oMyk7Cglmb3IgKGludCBpID0gMDsgaSA8IG47IGkrKykgewoJCWFbaV0gPSBpOwoJfQoJZXl0emluZ2VyKCk7Cgl7CgkJZG91YmxlIHRpbiA9IChkb3VibGUpY2xvY2soKTsKCQlpbnQgeCA9IDEsIGNoZWNrID0gMDsKCQlmb3IgKGludCBpID0gMDsgaSA8ICgxIDw8IDIwKTsgaSsrKSB7CgkJCXggPSB4b3JzaGlmdDMyKHgpOwoJCQljaGVjayBePSBzZWFyY2goeCk7CgkJfQoJCWRvdWJsZSB0b3V0ID0gKGRvdWJsZSljbG9jaygpOwoJCXN0ZDo6Y291dCA8PCAiZXl0emluZ2VyID0gIiA8PCAodG91dCAtIHRpbikgLyBDTE9DS1NfUEVSX1NFQyA8PCAicywgY2hlY2sgPSAiIDw8IGNoZWNrIDw8IHN0ZDo6ZW5kbDsKCX0KCXsKCQlkb3VibGUgdGluID0gKGRvdWJsZSljbG9jaygpOwoJCWludCB4ID0gMSwgY2hlY2sgPSAwOwoJCWZvciAoaW50IGkgPSAwOyBpIDwgKDEgPDwgMjApOyBpKyspIHsKCQkJeCA9IHhvcnNoaWZ0MzIoeCk7CgkJCWNoZWNrIF49IGludChzdGQ6Omxvd2VyX2JvdW5kKGEsYStuLHgpLWEpOwoJCX0KCQlkb3VibGUgdG91dCA9IChkb3VibGUpY2xvY2soKTsKCQlzdGQ6OmNvdXQgPDwgImxvd2VyX2JvdW5kID0gIiA8PCAodG91dCAtIHRpbikgLyBDTE9DS1NfUEVSX1NFQyA8PCAicywgY2hlY2sgPSAiIDw8IGNoZWNrIDw8IHN0ZDo6ZW5kbDsKCX0KCXJldHVybiAwOwp9