题目描述

小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. 使用hibernate框架连接oracle数据库进行简单的增删改

    初始化配置和session 关于配置文件这里就不在赘述了,假设配置文件配好后我们需要加载配置和sessionFactory,并获取session,因为每次进行增删改查时都需要session,所以封装成 ...

  2. 搭建ssm框架经验

    要想搭建好ssm框架的开发环境.首先我们需要知道ssm是什么?ssm就是spring,springmvc,mybatis. 然后我们要知道,他们分别都是怎样实现的和做什么用的,充当什么角色?这样我们就 ...

  3. Cacti 学习笔记

    Cacti是用php语言实现的一个软件,它的主要功能是用snmp服务获取数据,然后用rrdtool储存和更新数据,当用户需要查看数据的时候用rrdtool生成图表呈现给用户.因此,snmp和rrdto ...

  4. React学习(4)——向服务器请求数据并显示

    本文中涉及到的技术包括:node.js/express服务器的搭建.fetch发送数据请求. 在之前的几篇文章中,介绍了如何搭建基础的React项目,以及一些简单知识,现在,我们还需要掌握如何用Rea ...

  5. ThinkPHP创建应用

    新建一个文件 引入ThinkPHP文件

  6. 图解HTTP总结(8)——确认访问用户身份的认证

    Session 管理及 Cookie 应用 基于表单认证的标准规范尚未有定论,一般会使用Cookie来管理Session(会话). 基于表单认证本身是通过服务器端的Web应用,将客户端发送过来的用户I ...

  7. Windows和Linux系统下,虚拟环境安装的全面说明和详细步骤

    虚拟环境的创建和使用 用途: ​ 1.在同一台电脑安装同一个包的不同版本 2.记录项目所用的所有的包的版本,方便部署. 如何使用: 1.创建虚拟环境 mkvirtualenv 虚拟环境名 -p pyt ...

  8. PublicCMS 网站漏洞 任意文件写入并可提权服务器权限

    PublicCMS是目前网站系统中第一个采用JAVA架构 TOMCAT+Apcche+Mysql数据库架构的CMS网站,开源,数据承载量大,可以承载到上千万的数据量,以及用户的网站并发可达到上千万的P ...

  9. Electronic Devices【电子设备】

    Electronic Devices We may think we're a culture that gets rid of our worn technology at the first si ...

  10. Python3 适合初学者学习的银行账户登录系统

    一.所用知识点: 1. for循环与if判断的结合 2. %s占位符的使用 3. 辅助标志的使用(标志位) 4. break的使用 二.代码示例: ''' 银行登录系统 ''' uname = &qu ...