【题解】CF1553H-XOR and Distance
小清新 DS 题。
首先考虑怎么求 $x =0 $ 的情况。一个方法是以建立线段树的方式分治。
我们将 Trie 和线段树结合,构建一颗 trie - tree。其中树上的一条边和 trie 相同表示 \(0/1\),每个节点表示一个区间。
如果我们异或 \(2^k\),等价于把深度位 \(k\) 的节点的左右儿子交换。
所以对于每个节点记录与区间左右端点最近的距离即可,然后以 \(0 \to 2 ^k - 1\) 的顺序枚举,修改两次不同的位的深度所有节点。
时间复杂度 \(\mathcal{O}(k2^k + kn)\)。
#define N (1 << 19)
int k, n, rev[N], ans[N];
struct node{
int ls, rs, l, r, mn, mx, sum;
}a[N << 2];
vector<int>c[21];
void build(int x,int l,int r,int d){
a[x] = {0, 0, l, r, 1 << k, 1 << k, 1 << k};
c[d].pb(x);
if(l == r)return ;
int mid = (l + r) >> 1;
build(a[x].ls = (x << 1), l, mid, d + 1);
build(a[x].rs = (x << 1) + 1, mid + 1, r, d + 1);
}
#define L a[x].l
#define R a[x].r
void upd(int x){
if(L == R)return;
a[x].mn = min(a[a[x].ls].mn, (R - L + 1) / 2 + a[a[x].rs].mn);
a[x].mx = min(a[a[x].rs].mx, (R - L + 1) / 2 + a[a[x].ls].mx);
a[x].sum = min(min(a[a[x].ls].sum, a[a[x].rs].sum), a[a[x].ls].mx + a[a[x].rs].mn + 1);
}
void ins(int x,int pos){
if(L == R)a[x].mn = a[x].mx = 0;
else{
int mid = (L + R) >> 1;
if(mid >= pos)ins(a[x].ls, pos);
else ins(a[x].rs, pos);
upd(x);
}
}
int main() {
read(n), read(k);
build(1, 0, (1 << k) - 1, 0);
rp(i, (1 << k) - 1)rev[i] = (rev[i >> 1] >> 1) + (i & 1 ? (1 << (k - 1)) : 0);
rp(i, n){
int x; read(x);
ins(1, x);
}
ans[0] = a[1].sum;
rp(i, (1 << k) - 1){
int s = i ^ (i - 1), w = 0;
rep(j, 0, k - 1)if(1 & (s >> j)){
cmx(w, j);
go(x, c[j])swap(a[x].ls, a[x].rs);
}pre(j, w, 0)go(x, c[j])upd(x);
ans[rev[i]] = a[1].sum;
}
rep(i, 0, (1 << k) - 1)printf("%d ", ans[i]);
return 0;
}