[ABC252Ex] K-th beautiful Necklace
Petit_Souris · · 个人记录
退役老登诈尸,上号写个题解。
很显然状态数上界是
考虑随机打乱序列并取状态数乘积
显然可以在 trie 树上逐位二分。具体而言,对于
时间复杂度
::::info[Code]
#include <bits/stdc++.h>
using ll = long long;
using ld = long double;
using ull = unsigned long long;
using namespace std;
template <class T>
using Ve = vector<T>;
#define ALL(v) (v).begin(), (v).end()
#define pii pair<ll, ll>
#define rep(i, a, b) for(ll i = (a); i <= (b); ++i)
#define per(i, a, b) for(ll i = (a); i >= (b); --i)
#define pb push_back
bool Mbe;
ll read() {
ll x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
return x * f;
}
void write(ll x) {
if(x < 0) putchar('-'), x = -x;
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
}
const ll N = 75, T = 3e5, O = 4e7 + 9;
ll n, C, K, id[N], p[2][N], len[2];
mt19937 rnd(time(0));
Ve<ll> vec[N];
int ch[O][2], tot, sz[O];
ll seq[O], plen;
int pos[O];
void Ins(ll x) {
ll u = 0;
per(i, 59, 0) {
ll v = (x >> i) & 1;
if(!ch[u][v]) ch[u][v] = ++tot;
u = ch[u][v], sz[u]++;
}
}
void dfs(ll id, ll x, ll xsum) {
if(x == len[id] + 1) {
if(id == 0) Ins(xsum);
else seq[++plen] = xsum;
return ;
}
for(ll z : vec[p[id][x]]) dfs(id, x + 1, xsum ^ z);
}
bool Med;
int main() {
cerr << fabs(&Med - &Mbe) / 1048576.0 << "MB\n";
n = read(), C = read(), K = read();
rep(i, 1, n) {
ll x = read(), y = read();
vec[x].pb(y);
}
iota(id + 1, id + n + 1, 1ll);
ll Z = 1e5, bst = 0;
while(Z--) {
shuffle(id + 1, id + C + 1, rnd);
ll prod = 1, pos = C;
rep(i, 1, C) {
if(prod * vec[id[i]].size() > T) {
pos = i - 1;
break;
}
prod *= vec[id[i]].size();
}
if(prod > bst) {
len[0] = len[1] = 0;
rep(i, 1, pos) p[0][++len[0]] = id[i];
rep(i, pos + 1, C) p[1][++len[1]] = id[i];
bst = prod;
}
}
dfs(0, 1, 0), dfs(1, 1, 0);
ll ans = 0;
per(i, 59, 0) {
ll cnt = 0;
rep(j, 1, plen) {
ll v = (seq[j] >> i) & 1;
if(!~pos[j]) continue;
ll npos = ch[pos[j]][v ^ 1];
cnt += sz[npos];
}
if(cnt >= K) {
ans |= (1ll << i);
rep(j, 1, plen) {
ll v = (seq[j] >> i) & 1;
if(!~pos[j]) continue;
pos[j] = ch[pos[j]][v ^ 1];
if(!pos[j]) pos[j] = -1;
}
}
else {
K -= cnt;
rep(j, 1, plen) {
ll v = (seq[j] >> i) & 1;
if(!~pos[j]) continue;
pos[j] = ch[pos[j]][v];
if(!pos[j]) pos[j] = -1;
}
}
}
write(ans), putchar('\n');
cerr << "\n" << clock() * 1.0 / CLOCKS_PER_SEC * 1000 << "ms\n";
return 0;
}
::::