题目

传送门

解法

容易想到将所有权值都放在 \(\text{trie}\) 树上,就像这样(图是我嫖的):

原问题转化为配对 \(n-1\) 对叶子节点,每一对叶子节点的贡献是它们的异或。需要最小化总贡献。

考虑合并两棵子树,需要分别在子树选择一个叶子节点进行配对,假设为 \((x,y)\)\((x,y)\)\(\rm lca\) 肯定深度越深越优,因为 \(2^k>\sum_{i=0}^{k-1}2^i\)

这样,我们不妨将有两棵子树的点全部选为 \(\rm lca\),因为它肯定是合并这两棵子树最优的点。

如何合并?关于两棵子树内寻找某一条件的二元组的问题,我们用启发式合并。在每个节点存下子树的所有叶子权值。

由于启发式合并套了个查询函数,总时间复杂度 \(\mathcal O(n\log n\log a)\)

另外我真的觉得题解区的 dfs 和奇奇怪怪的优化时间复杂度不太对,可为什么都这么快?

代码

#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;

#define print(x,y) write(x),putchar(y)

template <class T> inline T read(const T sample) {
    T x=0; int f=1; char s;
    while((s=getchar())>'9'||s<'0') if(s=='-') f=-1;
    while(s>='0'&&s<='9') x=(x<<1)+(x<<3)+(s^48),s=getchar();
    return x*f;
}
template <class T> inline void write(const T x) {
    if(x<0) return (void) (putchar('-'),write(-x));
    if(x>9) write(x/10);
    putchar(x%10^48);
}

typedef long long ll;

const int maxn=2e5+5;

int n,a[maxn],idx;
int to[maxn*31][2];
vector <int> g[maxn*31];

void ins(int v) {
    int p=0;
    for(int i=30;i>=0;--i) {
        bool d=(v>>i&1);
        if(!to[p][d]) to[p][d]=++idx;
        p=to[p][d];
        g[p].push_back(v);
    }
}

ll ask(int o,int v,int dep) {
    ll ans=0;
    for(int i=dep;i>=0;--i) {
        bool d=(v>>i&1);
        if(to[o][d]) o=to[o][d];
        else {
            ans^=(1<<i);
            o=to[o][d^1];
        }
    }
    return ans;
}

ll query(int o,int dep) {
    if(dep<0) return 0;
    ll ans=0;
    if(to[o][0]) ans+=query(to[o][0],dep-1);
    if(to[o][1]) ans+=query(to[o][1],dep-1);
    if(!to[o][0] or !to[o][1]) return ans;
    bool d=(g[to[o][0]].size()>g[to[o][1]].size());
    ll mn=1e18;
    for(int i=0;i<g[to[o][d]].size();++i)   
        mn=min(mn,ask(to[o][d^1],g[to[o][d]][i],dep-1));
    return mn+ans+(1<<dep);
}

int main() {
    n=read(9);
    for(int i=1;i<=n;++i)
        a[i]=read(9);
    sort(a+1,a+n+1);
    n=unique(a+1,a+n+1)-a-1;
    for(int i=1;i<=n;++i)
        ins(a[i]);
    print(query(0,30),'\n');
	return 0;
}
posted on 2021-07-18 18:17  Oxide  阅读(63)  评论(0编辑  收藏  举报