小朋友排隊|2014年藍橋杯B組題解析第十題-fishers
阿新 • • 發佈:2019-01-18
ostream 拷貝 std 小朋友排隊 names 沒有 都是 歸並 數組
例如,輸入:
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 , 不能通過工程設置而省略常用頭文件。
提交時,註意選擇所期望的編譯器類型。
小朋友排隊
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
請嚴格按要求輸出,不要畫蛇添足地打印類似:“請您輸入...” 的多余內容。
所有代碼放在同一個源文件中,調試通過後,拷貝提交該源碼。
提交時,註意選擇所期望的編譯器類型。
思路:求逆序對:左邊大於它的 + 右邊小於它的數量,求完逆序對後,計算等差數列和 (因為不高興程度每次增加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