• 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;
    }
    
  • 相关阅读:
    c++运算符优先级
    C++中宽字符类型(wchar_t)的编码
    标志寄存器综述
    ubuntu 更新源
    windows shell命令相关
    汇编语言-环境搭建(16位)
    linux配置ftp
    ssl协议相关
    boost相关
    ubuntu下编译protobuf
  • 原文地址:https://www.cnblogs.com/Reanap/p/15996502.html
Copyright © 2020-2023  润新知