CF1553H XOR and Distance

猜猜这篇过多久才会被码农教程爬qwq。

好高妙啊。

考虑按位考虑。定义 \(f(x , d)\) , 表示所有与 \(x\) 最多只有前 \(d\) 位不同的所有 \(a_i\) 异或 \(x\) 的最小差。

考虑 \(d\) 增加 1 , 那么会多上一些 \(d + 1\) 位与 \(x\) 不同的数。

三种情况,答案在原集合,新集合,各占一个。

原集合容易处理,新集合就是 \(f(y , d) + 2^d\) ,其中 \(y\) 是只有 \(d + 1\) 位与 \(x\) 不同的数。

各占一个的情况,注意到新集合的数异或 \(x\) 的结果一定大于原集合的结果。因此维护 \(mxv(x , d)\) / \(miv(x , d)\) 表示所有与 \(x\) 只有前 \(d\) 位不同的所有 \(a_i\) 异或的最大/小值。

那么各占一个的贡献就是 \(miv(y , d) + 2^d - mxv(x , d)\)

同时这两个新的东西会相当好维护,令 \(d\) 增加 1 ,讨论一下就好了。

#include <map>
#include <set>
#include <queue>
#include <cmath>
#include <bitset>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define pii pair <int , int>
#define pll pair <LL , LL>
#define mp make_pair
#define fs first
#define sc second
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;

//const int Mxdt=100000; 
//static char buf[Mxdt],*p1=buf,*p2=buf;
//#define getchar() p1==p2&&(p2=(p1=buf)+fread(buf,1,Mxdt,stdin),p1==p2)?EOF:*p1++;

template <typename T>
void read(T &x) {
	T f=1;x=0;char s=getchar();
	while(s<'0'||s>'9') {if(s=='-') f=-1;s=getchar();}
	while(s>='0'&&s<='9') {x=(x<<3)+(x<<1)+(s-'0');s=getchar();}
	x *= f;
}

template <typename T>
void write(T x , char s='\n') {
	if(!x) {putchar('0');putchar(s);return;}
	if(x<0) {putchar('-');x=-x;}
	T tmp[25]={},t=0;
	while(x) tmp[t++]=x%10,x/=10;
	while(t-->0) putchar(tmp[t]+'0');
	putchar(s); 
}

int n , k , a[(1 << 20) + 5] , vis[(1 << 20) + 5];
int mav[(1 << 20) + 5][21] , miv[(1 << 20) + 5][21];
int f[(1 << 20) + 5][21] , ans[(1 << 20) + 5];

int main() {
	read(n),read(k);
	for (int i = 1; i <= n; ++i) read(a[i]) , vis[a[i]] = 1;
	
	for (int s = 0; s < (1 << k); ++s) {
		mav[s][0] = -1e9;miv[s][0] = 1e9;
		ans[s] = f[s][0] = 1e9;
		if(vis[s]) mav[s][0] = 0 , miv[s][0] = 0;
	}
	
	for (int d = 0; d < k; ++d) {
		for (int s = 0; s < (1 << k); ++s) {
			mav[s][d + 1] = max(mav[s][d] , mav[s ^ (1 << d)][d] + (1 << d));
			miv[s][d + 1] = min(miv[s][d] , miv[s ^ (1 << d)][d] + (1 << d));
			f[s][d + 1] = min(f[s][d] , min(f[s ^ (1 << d)][d] , miv[s ^ (1 << d)][d] + (1 << d) - mav[s][d]));
			ans[s] = min(ans[s] , f[s][d + 1]);
		}
	}
	
	for (int s = 0; s < (1 << k); ++s) write(ans[s] , ' ');
	
	return 0;
}
posted @ 2022-03-12 10:32  Reanap  阅读(27)  评论(0编辑  收藏  举报