Loading

【题解】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;
}
posted @ 2022-01-28 20:03  7KByte  阅读(53)  评论(0编辑  收藏  举报