题目描述

小C有一个N个数的整数序列,这个序列的中的数两两不同。小C每次可以交换序列中的任意两个数,代价为这两个数之和。小C希望将整个序列升序排序,问小C需要的最小代价是多少?

输入输出格式

输入格式:

第一行,一个整数N。

第二行,N个整数,表示小C的序列。

输出格式:

一行,一个整数,表示小C需要的最小代价。

输入输出样例

输入样例#1:

6
8 4 5 3 2 7
输出样例#1:

34

说明

数据范围:

对于30%的数据,1<=N<=10;

对于全部的数据,1<=N<=100000,输入数据中的其他整数均为正整数且不超过$10^9$。

Solution:

  本题貌似说是什么群论(可惜至少我现在不会,挖坑拉~手动滑稽~)。但是实际上,一点简单的思维(类似贪心)就可以做出来。

  首先我们假设原数列为数组$a$,目标数列为数组$b$($b$为$a$从小到大排序后的数组)。

  对比$a_i,b_i$,则我们容易发现,相互之间需要交换位置的数会出现在同一集合中(举样例:$8\;4\;5\;3\;2\;7$排序后为$2\;3\;4\;5\;7\;8$,此时整个数列分为了$2$个集合:$\begin{Bmatrix} 2\;7\;8\end{Bmatrix}$和$\begin{Bmatrix} 3\;4\;5\end{Bmatrix}$)。

  容易发现:当某一集合元素大于$size\geq 1$时,该集合内的数一定位置互异,且只需以其中$1$个数去和该集合中其他的$size-1$个数各交换一次,就能使得该集合元素大小和位置对应(可以用样例试试,我这里不模拟了)。

  再由题意中交换一次的代价的定义,很容易贪心想到:

  1、若只用同一集合中的元素交换,那么使得某一集合中的元素大小和位置对应需要的代价最小应该是用该集合中的最小元素$minn$去和其它元素交换,此时不妨假设某一集合$p$有$k$个元素,这$k$个元素之和为$sum$,设$p$中最小的元素为$p_1$,那么交换代价$cost=(p_1+p_2)+(p_1+p_3)+(p_1+p_4)+…+(p_1+p_{k-1})$,化简得$cost=(k-1)*p_1+sum-p_1=(k-2)*p_1+sum$。可以证明当该交换集合中的最小元素$p_1$同时是全集(即原数列$a$)中的最小值时,上述方法所求的$cost$即为该集合的最小代价。

  2、但是当$p$集合中的最小值不是$a$中最小值时,只用同一集合中的元素去交换不一定最优,因为我们可以将全集$a$中的最小值加入$p$集合可能会使$cost$更小(举例:原序列$a:\;1\;15\;11\;13\;14$,若按直接按上面的方法则花费为$75$,但实际上我们将$1$先和$11$进行一次交换代价为$1+11$,这样$1$就以当前最小的代价$12$加进了该交换集合,此时再去算答案为$69$)。由上面的例子容易想到,我们以最小的代价即将$minn$与$p_1$交换,此时$minn$加进了交换集合,则交换代价$cost=minn+p_1+(minn+p_1)+(minn+p_2)+…+(minn+p_k)=minn*(k+1)+tot+p_1$。此时比较一下两种情况,取最小代价。

  实现时,就按上述步骤,求交换集合,比较$ans$本题就$ok$了。

代码:

#include<bits/stdc++.h>
#define il inline
#define ll long long
#define inf 233333333333333
using namespace std;
const int N=;
il ll gi(){
ll a=;char x=getchar();bool f=;
while((x<''||x>'')&&x!='-')x=getchar();
if(x=='-')x=getchar(),f=;
while(x>=''&&x<='')a=a*+x-,x=getchar();
return f?-a:a;
}
ll n,ans,b[N],minn=inf;
struct point{
ll v,id;
bool operator <(point a){return v<a.v;}
}a[N];
bool vis[N];
int main()
{
n=gi();
for(int i=;i<=n;i++)a[i].v=gi(),a[i].id=i,b[i]=a[i].v,minn=min(minn,a[i].v);
sort(a+,a+n+);
for(int i=;i<=n;i++)
if(a[i].id!=i){
ll s=a[i].id,tot=b[i],l=,mn=b[i];
while(s!=i){
l++;
mn=min(mn,b[s]);
tot+=b[s];
swap(a[s].id,s);
}
if(mn==minn)ans+=tot+mn*(l-);
else ans+=min(minn*(l+)+mn+tot,tot+mn*(l-));
}
cout<<ans;
return ;
}

P2127 序列排序的更多相关文章

  1. [洛谷P2127] 序列排序

    洛谷题目链接:序列排序 题目描述 小C有一个N个数的整数序列,这个序列的中的数两两不同.小C每次可以交换序列中的任意两个数,代价为这两个数之和.小C希望将整个序列升序排序,问小C需要的最小代价是多少? ...

  2. 洛谷 P2127 序列排序

    https://www.luogu.org/problemnew/show/P2127 感觉题解里写的比较复杂,可能自己的想法比较简单一点吧. 看这个图中的的点如果形成一个环,贪心的考虑,要想花费最少 ...

  3. 洛谷P2127 序列排序 [贪心]

    题目传送门 题目描述 小C有一个N个数的整数序列,这个序列的中的数两两不同.小C每次可以交换序列中的任意两个数,代价为这两个数之和.小C希望将整个序列升序排序,问小C需要的最小代价是多少? 输入输出格 ...

  4. 从无序序列中求这个序列排序后邻点间最大差值的O(n)算法

    标题可能比较绕口,简单点说就是给你一个无序数列A={a1,a2,a3……an},如果你把这个序列排序后变成序列B,求序列B中相邻两个元素之间相差数值的最大值. 注意:序列A的元素的大小在[1,2^31 ...

  5. 【洛谷P2127】序列排序

    题目大意:给定一个长度为 N 的序列,序列中的数两两不相同,每次可以交换序列中任意两个数,代价为这两个数的和,问将序列调整为升序,最少的代价是多少. 题解:考虑这个问题的一个子问题,这个序列为 N 的 ...

  6. python学习-序列排序

    python的排序中,可以使用内置的sort()来对序列进行排序,也可以使用内置的sorted()函数对序列进行排序,区别是,当使用sort()时,是对原序列进行排序,而sorted()则是生成一个新 ...

  7. [LeetCode] Permutation Sequence 序列排序

    The set [1,2,3,…,n] contains a total of n! unique permutations. By listing and labeling all of the p ...

  8. 【Excel】将IP按照IP地址(v4)增长序列排序

    Background: Excel列中,有多个net-block, 将这些net-block按照IP地址(v4)自己的大小从小到大排序. Idea: IPv4地址的格式是点分十进制的,也就是说每一个点 ...

  9. List集合序列排序的两种方法

    首先讲一下Comparable接口和Comparator接口,以及他们之间的差异.有助于Collections.sort()方法的使用.请参考 1.Comparable自然规则排序//在自定义类Stu ...

随机推荐

  1. JavaScript--动态添加元素

    在网页中,使用JavaScript动态创建元素的方式有三种: 1.document.write() 2.Element.innerHTML 3.document.createElement() 在上述 ...

  2. 上传文件到阿里云linux服务器

    在“运行”中输入cmd,打开控制台,切换到刚才Putty的安装目录下,我的是E:\Putty,然后输入pscp命令,我们需要这个命令来实现文件的上传.如下图所示,命令格式为: pscp D:\recy ...

  3. 【php学习-5】

    mutil_query($result)){ //多查询 where } //执行查询 /* $result=$cone->query("SELECT * from test" ...

  4. 04 mysql 基础三 (进阶)

    mysql 基础三 阶段一 mysql 单表查询 1.查询所有记录 select * from department; ​ select * from student; ​ select * from ...

  5. Matplotlib 子图的创建

    在matplotlib中,整个图像为一个Figure对象 在Figure对象中可以包含一个或者多个Axes对象  每个Axes对象相当于一个子图了 每个Axes(ax)对象都是一个拥有自己坐标系统的绘 ...

  6. Kubernetes-GC

    Kubernetes集群中垃圾回收(Garbage Collection)机制由kubelet完成.kubelet定期清理不再使用的容器和镜像,每分钟进行一次容器的GC操作,每五分钟进行一次镜像的GC ...

  7. ansible结合SHELL搭建自己的CD持续交付系统

    一. 设计出发点 因公司业务面临频繁的迭代上线,一日数次.仅仅依靠手工效率过低且易出错. 考虑搭建一套可以满足现有场景的上线系统. 二 .为何采用ansible+shell方式 1.可控性(完全自主拥 ...

  8. A problem occurred evaluating project ':'. > ASCII

    项目编译出错: 错误信息如下: FAILURE: Build failed with an exception. * Where: Build file 'F:\git\i***\build.grad ...

  9. shell -- for、while用法

    #数字段形式for i in {1..10}do   echo $idone #详细列出(字符且项数不多)for File in 1 2 3 4 5do    echo $Filedone #对存在的 ...

  10. shell -- if参数用法

    一.概要1.if与[之间要有空格2.[]与判断条件之间也必须有空格3.]与:之间不能有空格 二.对字符串的判断1.if [ str1=str2 ];then fi  ----当两个字符串相同时返回真2 ...