題目傳送門
小c有乙個n個數的整數序列,這個序列的中的數兩兩不同。小c每次可以交換序列中的任意兩個數,代價為這兩個數之和。小c希望將整個序列公升序排序,問小c需要的最小代價是多少?
輸入格式:
第一行,乙個整數n。
第二行,n個整數,表示小c的序列。
輸出格式:
一行,乙個整數,表示小c需要的最小代價。
輸入樣例#1: 複製
68 4 5 3 2 7
輸出樣例#1: 複製
34
資料範圍:
對於30%的資料,1<=n<=10;
對於全部的資料,1<=n<=100000,輸入資料中的其他整數均為正整數且不超過109。
分析:很顯然的貪心。因為每次只能交換兩個數,那麼每次都拿小的數來交換肯定會更優。但肯定不會這麼簡單。首先從樣例分析,樣例中的8,2,7這三個數只要互相交換就可以到達目標位置,也就是說這三個數形成了乙個「環」,那麼每次就照這樣的環,將環中的每乙個數歸位的最小花費只有兩種情況:要麼就每次都拿環中最小的數與每乙個數相互交換,要麼就拿整個序列中最小的數與環中每個數交換。不過要注意,第二種情況交換的時候有乙個數會交換兩次(可以自己模擬一下),那麼肯定就將環中最小的數交換兩次最優。具體看**:
code:
#include#include#include
#include
#include
#include
#include
using
namespace
std;
const
int n=1e5+7
;int
n;bool
vis[n];
long
long
ans;
struct
nodea[n];
inline
intread()
while(ch>='
0'&&ch<='9')
return flag?-num:num;
}bool
cmp(node x,node y)
inline
void work(int
x)
long
long a1=num+(tot-2)*minn;
long
long a2=num+(tot+1)*a[1].val+minn;
ans+=min(a1,a2);
}int
main()
sort(a+1,a+n+1
,cmp);
for(int i=1;i<=n;i++)
if(!vis[i])
work(i);
printf(
"%lld
",ans);
return0;
}
洛谷 P1645 序列
炒雞明顯的貪心題,主要就想讓一段區間與另一段裡面重合的數越多越好。於是先按照區間右端排序,然後盡可能的把數都往右靠攏,最後與另一段區間的前面的重合。然後可以用個flag來記錄哪些數被選了什麼的。include includeusing namespace std const int maxn 100...
洛谷 P1631 序列合併
題目描述 有兩個長度都是n的序列a和b,在a和b中各取乙個數相加可以得到n 2個和,求這n 2個和中最小的n個。輸入輸出格式 輸入格式 第一行乙個正整數n 第二行n個整數ai,滿足ai ai 1且ai 10 9 第三行n個整數bi,滿足bi bi 1且bi 10 9.資料規模 對於50 的資料中,滿...
洛谷 P1631 序列合併
有兩個長度都是n的序列a和b,在a和b中各取乙個數相加可以得到n 2個和,求這n 2個和中最小的n個。第一行乙個正整數n 第二行n個整數ai,滿足ai ai 1且ai 10 9 第三行n個整數bi,滿足bi bi 1且bi 10 9.輸出僅一行,包含n個整數,從小到大輸出這n個最小的和,相鄰數字之間...