题目描述

小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. 高级同步器:信号量Semaphore

    引自:https://blog.csdn.net/Dason_yu/article/details/79734425 一.信号量一个计数信号量.从概念上讲,信号量维护了一个许可集.Semaphore经 ...

  2. weex踩坑记录

    weex框架样式问题--我暂时使用最基本的样式css,weex前端开发的话web端会显示各种的html标签.写出的样式也都会显示的很好,但是在app端的话,就没有很好的兼容性,只是支持文档中的一些标签 ...

  3. linux中安装node

    1.去官网下载和自己系统匹配的文件: 英文网址:https://nodejs.org/en/download/ 中文网址:http://nodejs.cn/download/ 通过 uname -a ...

  4. ELK 安装部署实战 (最新6.4.0版本)

    一.实战背景 根据公司平台的发展速度,对于ELK日志分析日益迫切.主要的需求有: 1.用户行为分析 2.运营活动点击率分析 作为上述2点需求,安装最新版本6.4.0是非常有必要的,大家可根据本人之前博 ...

  5. Static关键字,遇到的问题_1

    一.问题 父类代码:                                                                                          ...

  6. Python的jieba模块简介

    现如今,词云技术遍地都是,分词模块除了jieba也有很多,主要介绍一下jieba的基本使用 import jieba import jieba.posseg as psg from os import ...

  7. linux几条基本命令和解释

    pwd 查看当前目录/     根目录ls    查看当前目录所包含文件ls -l    查看当前目录所包含文件的详细信息d rwx rwx r-x 1 root root1  2     3   4 ...

  8. 当安装mongodb客户端出现了Failed to load list of databases

    在装mongodb最新版(4.1.5开发版)服务后,我用robo3t打开它的时候遇到了这个问题. 最直接的解决办法就是换一个mongodb版本,https://github.com/Studio3T/ ...

  9. kafka重置offset

    kafka重置offset   1.删除zookeeper上节点信息 打开client :./zkCli.sh -server 127.0.0.1:12181 删除consumer:rmr /cons ...

  10. ajax同步和异步的切换

    ajax为网页提供了非常不错的异步机制,但是有时候两个ajax放在一起,希望第一个完成后再继续第二个ajax的执行.这时候可以将第一个ajax代码带上同步参数即可,如下: $.ajax({ async ...