洛谷P2127 序列排序 貪心

2022-04-30 10:12:13 字數 1452 閱讀 5544

題目傳送門

小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,輸入資料中的其他整數均為正整數且不超過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個最小的和,相鄰數字之間...