• FR #5题解


    A.

      首先建一棵01trie。每一个节点的子树都代表一个集合,然后显然在左儿子和右儿子,即相邻的集合连边费用最少(遵循kruskal.)

         就完了。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxn 100500
    #define inf 2147483646
    using namespace std;
    long long n,w[maxn],ls[maxn*15],rs[maxn*15],size[maxn*15],tot=0,ans=0,root,mn;
    void insert(long long &now,long long bit,long long x)
    {
        if (!now) now=++tot;size[now]++;
        if (bit==-1) return;
        long long nb=x&(1<<bit);
        if (!nb) insert(ls[now],bit-1,x);
        else insert(rs[now],bit-1,x);
    }
    long long dfs3(long long now,long long bit,long long num)
    {
        if (bit==-1) return 0;
        long long nb=num&(1<<bit);
        if (!nb) 
        {
            if (ls[now]) return dfs3(ls[now],bit-1,num);
            else return dfs3(rs[now],bit-1,num)+(1<<bit);
        }
        else
        {
            if (rs[now]) return dfs3(rs[now],bit-1,num);
            else return dfs3(ls[now],bit-1,num)+(1<<bit);
        }
    }
    void dfs2(long long now,long long bit,long long num,long long pos,long long nx,long long pb)
    {
        if (!now) return;
        if (bit==-1)
        {
            mn=min(mn,dfs3(pos,pb,num)+nx);
            return;
        }
        dfs2(ls[now],bit-1,num<<1,pos,nx,pb);
        dfs2(rs[now],bit-1,num<<1|1,pos,nx,pb);
        return;
    }
    void dfs1(long long now,long long bit,long long num)
    {
        if ((bit==-1) || (!now)) return;
        dfs1(ls[now],bit-1,num<<1);
        dfs1(rs[now],bit-1,num<<1|1);
        if ((!ls[now]) || (!rs[now])) return;
        if (size[ls[now]]<=size[rs[now]]) {mn=inf;dfs2(ls[now],bit-1,num<<1,rs[now],1<<bit,bit-1);ans+=mn;}
        else {mn=inf;dfs2(rs[now],bit-1,num<<1|1,ls[now],1<<bit,bit-1);ans+=mn;}
        return;
    }
    int main()
    {
        scanf("%lld",&n);
        for (long long i=1;i<=n;i++)
        {
            scanf("%lld",&w[i]);
            insert(root,30,w[i]);
        }
        dfs1(root,30,0);
        printf("%lld\n",ans);
        return 0;
    }

    B.

      直接枚举gcd再枚举倍数连边,复杂度调和级数nlogn。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxn 100500
    using namespace std;
    int n,father[maxn];
    int ans=0;
    int getfather(int x)
    {
        if (x!=father[x])
            father[x]=getfather(father[x]);
        return father[x];
    }
    int main()
    {
        scanf("%d",&n);
        for (int i=1;i<=n;i++) father[i]=i;
        for (int d=n/2;d>=1;d--)
            for (int i=2;i*d<=n;i++)
            {
                int x=(i-1)*d,y=i*d,w=d;
                int f1=getfather(x),f2=getfather(y);
                if (f1!=f2) {father[f1]=f2;ans+=w;}
            }
        printf("%d\n",ans);
        return 0;
    }

    C.

      三角剖分还要nlogn?。。。弃坑。

  • 相关阅读:
    samtools flags 分解
    epollo
    springaop 执行顺序问题
    java解析String类型的xml
    服务器调用服务器接口之间的抓包
    windows下mysql忘了安装时的root密码
    docker+jenkins+gitlab自动化构建
    influxdb基本操作
    记一次CPU过高排查过程
    dockercompose部署一个可远程连接的容器
  • 原文地址:https://www.cnblogs.com/ziliuziliu/p/6276961.html
Copyright © 2020-2023  润新知