問題描述
n 個小朋友站成一排。現在要把他們按身高從低到高的順序排列,但是每次只能交換位置相鄰的兩個小朋友。
每個小朋友都有乙個不高興的程度。開始的時候,所有小朋友的不高興程度都是0。
如果某個小朋友第一次被要求交換,則他的不高興程度增加1,如果第二次要求他交換,則他的不高興程度增加2(即不高興程度為3),依次類推。當要求某個小朋友第k次交換時,他的不高興程度增加k。
請問,要讓所有小朋友按從低到高排隊,他們的不高興程度之和最小是多少。
如果有兩個小朋友身高一樣,則他們誰站在誰前面是沒有關係的。
輸入格式
輸入的第一行包含乙個整數n,表示小朋友的個數。
第二行包含 n 個整數 h1 h2 … hn,分別表示每個小朋友的身高。
輸出格式
輸出一行,包含乙個整數,表示小朋友的不高興程度和的最小值。
樣例輸入
33 2 1
樣例輸出
9樣例說明
首先交換身高為3和2的小朋友,再交換身高為3和1的小朋友,再交換身高為2和1的小朋友,每個小朋友的不高興程度都是3,總和為9。
資料規模和約定
對於10%的資料, 1<=n<=10;
對於30%的資料, 1<=n<=1000;
對於50%的資料, 1<=n<=10000;
對於100%的資料,1<=n<=100000,0<=hi<=1000000。
剛讀完題給我的感覺就是有點像氣泡排序的過程,於是沿著這個思路我就想到了逆序對,然後看資料量發現暴力肯定是不行,幸好之前做過用樹狀陣列求解逆序對,然後就完美的卡住了。。。。
首先這個題不是普通的求解逆序對,因為移動兩個小朋友都會使得雙方增加不高興值,我們就必須要得到每個小朋友移動的次數。乙個小朋友移動的原因肯定是他前面有比他大的或者他後面有比他小的,順著這個思路我們就可以在輸入的時候找到他前面比他大的。然後再倒著遍歷一下找比他小的。這樣也就求得了以當前位置為基準得到的逆序對的數量,也就是當前位置移動的次數。
第一次暴力**得了60分:
#include
#include
#include
#include
using
namespace std;
int arr[
100005
],sum[
100005];
intmain()
long
long res =0;
for(
int i=
1;i<=n;i++
) res +
=(sum[i]+1
)*sum[i]/2
; cout
}
ac**:
#include
#include
#include
#include
using
namespace std;
#define lowbit(x) x&(-x)
#define maxn 100005
const
int maxh =
1000005
;//身高最大值
//height記錄學生身高,樹狀陣列使用cnt,num用來記錄逆序對的數量
int height[maxn]
,cnt[maxh]
,num[maxn]
;long
long arr[maxn]
;//等差前n項和打表,移動n次就是1~n的和
void
init()
int n;
void
add(
int x,
int y)
}int
sum(
int x)
return ans;
}int
main()
//倒著找,找比他矮的
memset
(cnt,0,
sizeof
(cnt));
for(
int i=n;i>=
1;i--
)long
long res =0;
for(
int i=
1;i<=n;i++
) res +
= arr[num[i]];
cout
}
藍橋杯 試題 歷屆試題 小朋友排隊 樹狀陣列
問題描述 n 個小朋友站成一排。現在要把他們按身高從低到高的順序排列,但是每次只能交換位置相鄰的兩個小朋友。每個小朋友都有乙個不高興的程度。開始的時候,所有小朋友的不高興程度都是0。如果某個小朋友第一次被要求交換,則他的不高興程度增加1,如果第二次要求他交換,則他的不高興程度增加2 即不高興程度為3...
藍橋杯 歷屆試題 小朋友排隊
歷屆試題 小朋友排隊 時間限制 1.0s 記憶體限制 256.0mb 問題描述 n 個小朋友站成一排。現在要把他們按身高從低到高的順序排列,但是每次只能交換位置相鄰的兩個小朋友。每個小朋友都有乙個不高興的程度。開始的時候,所有小朋友的不高興程度都是0。如果某個小朋友第一次被要求交換,則他的不高興程度...
藍橋杯 歷屆試題 小朋友排隊
時間限制 1sec 記憶體限制 128mb 提交 75 解決 11 題目描述 n 個小朋友站成一排。現在要把他們按身高從低到高的順序排列,但是每次只能交換位置相鄰的兩個小朋友。每個小朋友都有乙個不高興的程度。開始的時候,所有小朋友的不高興程度都是0。如果某個小朋友第一次被要求交換,則他的不高興程度增...