1. 程式人生 > >小朋友排隊|2014年藍橋杯B組題解析第十題-fishers

小朋友排隊|2014年藍橋杯B組題解析第十題-fishers

ostream 拷貝 std 小朋友排隊 names 沒有 都是 歸並 數組

小朋友排隊

n 個小朋友站成一排。現在要把他們按身高從低到高的順序排列,但是每次只能交換位置相鄰的兩個小朋友。
每個小朋友都有一個不高興的程度。開始的時候,所有小朋友的不高興程度都是0。
如果某個小朋友第一次被要求交換,則他的不高興程度增加1,如果第二次要求他交換,則他的不高興程度增加2(即不高興程度為3),依次類推。當要求某個小朋友第k次交換時,他的不高興程度增加k。
請問,要讓所有小朋友按從低到高排隊,他們的不高興程度之和最小是多少。
如果有兩個小朋友身高一樣,則他們誰站在誰前面是沒有關系的。
【數據格式】
輸入的第一行包含一個整數n,表示小朋友的個數。 第二行包含 n 個整數 H1 H2 … Hn,分別表示每個小朋友的身高。 輸出一行,包含一個整數,表示小朋友的不高興程度和的最小值。

例如,輸入:
3
3 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。
資源約定: 峰值內存消耗 < 256M CPU消耗 < 1000ms
請嚴格按要求輸出,不要畫蛇添足地打印類似:“請您輸入...” 的多余內容。
所有代碼放在同一個源文件中,調試通過後,拷貝提交該源碼。
註意: main函數需要返回0 註意: 只使用ANSI C/ANSI C++ 標準,不要調用依賴於編譯環境或操作系統的特殊函數。 註意: 所有依賴的函數必須明確地在源文件中 #include , 不能通過工程設置而省略常用頭文件。
提交時,註意選擇所期望的編譯器類型。

思路:求逆序對:左邊大於它的 + 右邊小於它的數量,求完逆序對後,計算等差數列和 (因為不高興程度每次增加k)

待改進:只能過50%的數據,超時了。後面用歸並排序 和 樹狀數組改進。

#include<iostream>
using namespace std;

int n;
int arr[1000010];
long long ans = 0;

/*
求逆序對:左邊大於它的 + 右邊小於它的數量
求完逆序對後,計算等差數列和 (因為不高興程度每次增加k)
*/ 

long long cal(long long x){
    return x + x*(x-1)/2;
}

int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>arr[i];
    }
    for(int i=1;i<=n;i++){
        long long ans1 = 0;
        long long ans2 = 0;
        for(int j=1;j<i;j++){
            if(arr[j] > arr[i]){
                ans1++;
            }
        }
        for(int j=i+1;j<=n;j++){
            if(arr[j]<arr[i]){
                ans2++;
            }
        }
        ans+=cal(ans1 + ans2); 
    }
    cout<<ans<<endl;
}

小朋友排隊|2014年藍橋杯B組題解析第十題-fishers