浪潮2020筆試 搬石頭,01串

2021-10-12 09:39:17 字數 1266 閱讀 1073

沙灘按照線型擺放著n個大小不一的球形石頭,已知第i個石頭的半徑為ri,且不存在兩個石頭有相同的半徑。為了使石頭的擺放更加美觀,現要求擺放的石頭的半徑從左往右依次遞增。因此,需要對一些石頭進行移動,每次操作可以選擇乙個石頭,並把它放在剩下n-1個石頭在最左邊或最右邊。問最少需要操作多少次才能將這n個石頭的半徑變成公升序?

輸入描述

第一行乙個整數n,表示石頭的個數。(1 <= n <= 100000)

第二行n個整數,表示從左往右石頭的半徑r1,r2,...,rn。(1 <= ri <= n),且保證不存在兩個不同的石頭擁有相同的半徑。 

輸出描述

最少操作次數

樣例輸入

54 1 2 5 3

樣例輸出

2一開始以為是逆序對,然後又往最長上公升子串行那裡想,發現n-最長上公升子串行正好是答案,而且樣例是可以做出來的。但是我自己舉了個例子沒有做出來。所以我又想了一會兒其他的。

然後神奇的事情發生了:我想先交乙個最長上公升子串行的**試試(o(n^2)的dp寫法),結果一交,tle,過了64%。我當時都驚呆了,資料量是10w,tle那說明答案就是最長上公升子串行啊, 只是我的 n^2 寫法超時了,然後我就開始寫貪心+二分的o(nlogn)寫法的最長上公升子串行。寫完後交上發現wrong answer??????難道是我貪心+二分寫崩了?然後瘋狂的查錯,也沒發現啥錯誤。

後來,才推出來正確的答案應該是最長+1連續上公升子串行(比如 2 3 4 5這種)。其實也比較好理解,因為如果中間不是+1這種連續的話,到時候還得往外移動。

舉個例子: 3 1 2 4 其最長上公升子串行是1 2 4,但是這個4是不應該計算的,因為3不可能直接插入到2 4中間,必須先把3放到最後,再把4放到最後這樣執行兩步。

所以,只要是連續+1的這種子串行,我們都不用移動,而只移動剩下的那些。

答案是n-最長+1連續上公升子串行的長度。

怎麼求最長+1連續上公升子串行?很簡單,a[i] 只能由 a[i]-1 轉移過來。

所以我們定義f[i] 表示以 i 結尾的最長+1連續上公升子串行的長度是 f[i] 。狀態轉移方程是: f[i]=f[i-1]+1;

#includeusing namespace std;

const int maxn=10000;

int a[maxn],f[maxn];

int main()

華為2020筆試

輸入n個字元,求他們有多少種排列 abc 6種 abc acb.aab 3種 n 8 數列範圍較小,所以直接全排列,暴力判重,就是不知道為啥乙個點一直沒過。判斷讀入為空的原因?include includeusing namespace std int g 100000 10 int a 10 in...

2020阿里實習4 22筆試

給定倆個整數n和m,n能拆分成m個數的和,對於任何乙個數字組合不能同時滿足以下兩個條件 任取乙個數字 1 該數的前乙個數比它大 2 該數的後乙個數比它大 問題是求出在這樣的條件下拆分n的最大組合數。例如 輸入5 3 輸出5示例解釋 error不滿足 解決思路 深搜 剪枝,複雜度o n m m 暫時沒...

美團2020筆試 字串逆排序

題目描述 將以逗號分隔的輸入字串按z a的順序排序,空字元位於最前面,當乙個字串是另乙個字串的子串時,排在前面。import sys import operator def resort arr n len arr count 0 for i in range n if arr i arr i ar...