zoukankan      html  css  js  c++  java
  • [CF888G] Xor-mst (Trie 树,最小生成树)

    题目链接


    Solution

    (Trie) 树 + 启发式合并.
    考虑到是异或,于是按位贪心.让高位的尽量相同.
    然后要计算每棵子树的代价,似乎并没有很好的方法??
    于是只能启发式合并.
    对于每一个有两个子节点的点;
    (siz) 较小的点中的值放到 (siz) 较大的子树中去查询即可.
    时间复杂度 (O(n(logn)^2)) .

    Code

    Dark 鸡哥 的代码:

    //It is made by Awson on 2018.3.18
    #include <bits/stdc++.h>
    #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;
        vector<int>key[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
    ", ans);
    }
    int main() {work(); return 0; } 
    
    

    我的代码(有问题):

    #include<bits/stdc++.h>
    #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 <ll>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<nn;i++)
        now=min(now,query(a[lx][i],rx));
        now=(now==inf?0:now);
    
        ans+=cf[t[u]]+now;
        return ;
    }
    
    int main()
    {
      freopen("a.in","r",stdin);
      freopen("a.ans","w",stdout);
        scanf("%lld",&n);
        cf[0]=1; for(ll i=1;i<=40;i++) cf[i]=cf[i-1]*2;
        for(ll i=1;i<=n;i++)
          scanf("%lld",&w[i]);
        sort(w+1,w+n+1);  n=unique(w+1,w+n+1)-w-1;
        for(ll i=1;i<=n;i++) insert(w[i]);
        solve(0);
        printf("%lld
    ",ans);
        return 0;
    }
    
    
  • 相关阅读:
    python中的map,fliter,reduce用法
    python中的函数参数传递
    python中的全局变量和局部变量
    python中的函数定义
    python中的eval()和exec()函数
    kafka手动提交,丢失数据
    02-基本概念
    01-接触kafka
    (8)适配模式--结构性
    java内存划分
  • 原文地址:https://www.cnblogs.com/Kv-Stalin/p/9588612.html
Copyright © 2011-2022 走看看