题面
https://www.luogu.org/problem/CF888G
题解
#include<cstdio> #include<iostream> #include<cstring> #include<vector> #define ri register int #define N 200050 #define LL long long #define INF (1<<30) using namespace std; int n; int a[N]; LL ans=0; inline int dit(int x,int i){ if (x&(1<<i)) return 1; else return 0; } struct TRIE { int ch[N*30][2],tot; void init() {tot=0;} void clear() { for (ri i=0;i<=tot;i++) ch[i][0]=ch[i][1]=0; tot=0; } void insert(int x) { int now=0; for (ri i=30;i>=0;i--) { int d=dit(x,i); if (!ch[now][d]) ch[now][d]=++tot; now=ch[now][d]; } } int search(int x) { int ret=0,now=0; for (ri i=30;i>=0;i--) { int d=dit(x,i); if (ch[now][d]) now=ch[now][d]; else now=ch[now][d^1],ret+=(1<<i); } return ret; } } trie; void solve(vector<int> s,int d){ int l=s.size(); if (l==0 || l==1) return; if (d==-1) return; vector<int> s1,s2; s1.clear(); s2.clear(); for (ri i=0;i<l;i++) if (s[i]&(1<<d)) s1.push_back(s[i]); else s2.push_back(s[i]); int l1=s1.size(),l2=s2.size(); if (l1 && l2) { trie.clear(); int ret=INF; for (ri i=0;i<l1;i++) trie.insert(s1[i]); for (ri i=0;i<l2;i++) ret=min(ret,trie.search(s2[i])); ans+=ret; solve(s1,d-1); solve(s2,d-1); } else if (l1) solve(s1,d-1); else solve(s2,d-1); } int main(){ scanf("%d",&n); for (ri i=1;i<=n;i++) scanf("%d",&a[i]); vector<int> s; s.clear(); for (ri i=1;i<=n;i++) s.push_back(a[i]); trie.init(); solve(s,30); cout<<ans<<endl; return 0; }