zoukankan      html  css  js  c++  java
  • 洛谷 P2127 序列排序

    https://www.luogu.org/problemnew/show/P2127

    感觉题解里写的比较复杂,可能自己的想法比较简单一点吧。

    看这个图中的的点如果形成一个环,贪心的考虑,要想花费最少,那么我们一定要多次利用最小那个点。

    图中来看就是2和6交换,然后2和4交换,然后就交换完了。

    然而还有一种换法就是,这个环中最小的点和序列中最小的点先交换,然后在进行环内的操作(就是说先2和1交换...)。

    所以对于每个点dfs找到环,然后判断两种方法哪种更优,统计答案。

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    #define LL long long
    #define inf 2147483647
    LL n,a[100006],b[100006],MIN,pos[100006],siz,sum,minn;
    bool vis[100006];
    LL ans;
    void dfs(int x)
    {
        if(vis[x])return ;
        sum+=a[x];    //记录环内每个点的总和 
        siz++;        //环内有多少个点 
        MIN=min(MIN,a[x]);    //环内最小值 
        vis[x]=1;    //打上标记 
        dfs(pos[x]);    //下一个点 
    }
    int main()
    {
        scanf("%d",&n);
        minn=MIN=inf;
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&a[i]);
            b[i]=a[i];
            minn=min(minn,a[i]);    //记录序列最小值 
        }
        sort(b+1,b+1+n);    //排序 
        for(int i=1;i<=n;i++)
            pos[i]=lower_bound(b+1,b+1+n,a[i])-b;    //记录排序后的位置 
        for(int i=1;i<=n;i++)
        {
            if(!vis[i])
            {
                dfs(i);
                ans+=min(sum+MIN+minn*(siz+1),sum+MIN*(siz-2));
    /*
            方法一:交换序列最小值和环内最小值 + 序列最小值 * 环内点数 
            方法二:环内最小值*环内点数。 
    */ 
                siz=0; sum=0; MIN=inf;
            }
        }
        printf("%lld",ans);
    }
  • 相关阅读:
    (九)MySQL数据库
    (八)其他组件(redis、zk、dubbo、MQ、ES)
    (七)Spring体系
    (六)JVM虚拟机
    (五)并发编程与锁机制
    (四)常用集合与原理
    (三)JDK版本区别
    k8s scheduler framework 配置weight不生效的问题
    Elasticsearch ILM delete not working
    etcd 依赖采坑
  • 原文地址:https://www.cnblogs.com/rmy020718/p/9776065.html
Copyright © 2011-2022 走看看