题目链接
Solution
\(Trie\) 树 + 启发式合并.
考虑到是异或,于是按位贪心.让高位的尽量相同.
然后要计算每棵子树的代价,似乎并没有很好的方法??
于是只能启发式合并.
对于每一个有两个子节点的点;
将 \(siz\) 较小的点中的值放到 \(siz\) 较大的子树中去查询即可.
时间复杂度 \(O(n(logn)^2)\) .
Code
Dark 鸡哥 的代码:
//It is made by Awson on 2018.3.18
#include
#define LL long long
using namespace std;
const int N = 200000;
const LL INF = 1e18;
int n, a[N+5], A[40]; LL bin[40], ans;
struct Trie {
int ch[N*35][2], bit[N*35+5], pos;
vectorkey[N*35];
void insert(int t) {
int u = 0; key[u].push_back(t);
for (int i = 35; i >= 1; i--) {
if (ch[u][A[i]] == 0) ch[u][A[i]] = ++pos; u = ch[u][A[i]];
t -= bin[i-1]*A[i], key[u].push_back(t), bit[u] = i;
}
}
LL qry(int u, int t) {
LL ans = 0;
for (int i = 1; i <= bit[u]-1; i++) A[i] = t%2, t /= 2;
for (int i = bit[u]-1; i >= 1; i--) {
if (ch[u][A[i]] != 0) u = ch[u][A[i]];
else u = ch[u][A[i]^1], ans += bin[bit[u]-1];
}
return ans;
}
LL query(int o) {
if (key[o].size() == 1) return 0;
if (ch[o][0]) ans += query(ch[o][0]);
if (ch[o][1]) ans += query(ch[o][1]);
if (!ch[o][0] || !ch[o][1]) return 0;
LL tmp = INF; int flag = 0;
if (key[ch[o][0]].size() > key[ch[o][1]].size()) flag = 1;
int sz = key[ch[o][flag]].size();
for (int i = 0; i < sz; i++) tmp = min(qry(ch[o][flag^1], key[ch[o][flag]][i]), tmp);
return tmp+bin[bit[o]-2];
}
}T;
void work() {
scanf("%d", &n); bin[0] = 1; for (int i = 1; i <= 35; i++) bin[i] = (bin[i-1]<<1);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
sort(a+1, a+n+1); n = unique(a+1, a+n+1)-a-1;
for (int i = 1; i <= n; i++) {
for (int j = 1, t = a[i]; j <= 35; j++) A[j] = t%2, t /= 2; T.insert(a[i]);
}
ans += T.query(0); printf("%I64d\n", ans);
}
int main() {work(); return 0; }
我的代码(有问题):
#include
#define ll long long
using namespace std;
const ll maxn=250008;
const ll inf=1926081737;
ll ch[maxn*40][2];
ll n,tot,t[maxn*40];
ll w[maxn],cf[43],ans;
vector a[maxn];
void insert(ll x)
{
ll u=0;
for(ll i=35;i>=0;i--)
{
ll c=(x>>i)&1;
if(!ch[u][c]) ch[u][c]=++tot;
a[u].push_back(x);x-=c*cf[i];
t[u]=i;
u=ch0[u][c];
}
}
ll query(ll x,ll u)
{
ll now=0,nn=t[u];
for(ll i=nn;i>=0;i--)
{
ll c=(x>>i)&1;
if(ch[u][c]) u=ch[u][c];
else u=ch[u][c^1],now+=cf[i];
}
return now;
}
void solve(ll u)
{
if(a[u].size()==1) return;
for(ll i=0;i<2;i++)
if(ch[u][i]) solve(ch[u][i]);
if(!ch[u][0]||!ch[u][1]) return;
ll lx=ch[u][0],rx=ch[u][1];
if(a[lx].size()>a[rx].size())
swap(lx,rx);
ll now=inf,nn=a[lx].size();
for(ll i=0;i