51nod選擇子串行 單調棧 分治

2021-08-15 16:08:49 字數 1282 閱讀 5143

1153 選擇子串行

codility

基準時間限制:1 秒 空間限制:131072 kb 分值: 40 

難度:4級演算法題

長度為n的整數陣列a,所有的數均不相同,假設下標從0開始。找到乙個最長的陣列b,b陣列的長度為k,數值範圍是0 - n - 1,記錄的是a陣列的下標。滿足a[b[0]] > a[b[1]] > a[b[2]] >...a[b[k]],並且對任意連續的兩項b[i]及b[i + 1],滿足min(b[i],b[i + 1]) < j < max(b[i],b[i + 1]) 均有a[j] < a[b[i + 1]] ,求最大的k。例如:9, 10, 2, -1, 3, -5, 0, -3, 1, 12, 5, 8, -2, 6, 4。可以選出:12, 10, 3, 1, 0, -3。對應的下標為:9, 1, 4, 8, 6, 7(就是b陣列),輸出6。

input

第1行:乙個數n,表示a陣列的長度。(1 <= n <= 50000)

第2 - n + 1行:每行1個數對應a陣列的元素ai(0 output

輸出b陣列最長的長度k。

input示例

15910

2-13-5

0-3112

58-26

4

output示例

6

李陶冶(題目提供者)

c++ 11的執行時限為:1000 ms ,空間限制為:131072 kb 

示例及語言說明請按這裡

題意:找乙個下降序列,要求相鄰的兩位滿足題目的要求。

思路:顯然,b陣列第乙個數是a陣列的最大數下標,假如不是,將此下標放到b陣列首位可以獲得更優解。因此得出如下簡單分治方法o(nlogn),為什麼不會超時呢?因為資料弱,沒有單調遞減的樣例,並不會退化到o(n*n)。那如果資料加強了怎麼辦呢?顯然可以用線段樹或其他辦法預處理出區間的最大值,遞迴時就無需每次都遍歷了。另外的方法就是單調棧,我們預處理每個數左右最近的比自己大的數的下標l[i]和r[i],留意到遞迴過程找到的分界點下標,i必然就是l[i]的右界和r[i]的左界,因此o(n)可以解決本題。

ac_1:

# include using namespace std;

const int maxn = 5e4+30;

int h[maxn];

int solve(int l, int r)

int main()

printf("%d\n",solve(1, n, id));

return 0;

}

51nod 1153 選擇子串行(單調佇列)

題目 長度為n的整數陣列a,所有的數均不相同,假設下標從0開始。找到乙個最長的陣列b,b陣列的長度為k,數值範圍是0 n 1,記錄的是a陣列的下標。滿足a b 0 a b 1 a b 2 a b k 並且對任意連續的兩項b i 及b i 1 滿足min b i b i 1 j max b i b i...

51NOD 最長公共子串行問題

給出兩個字串a b,求a與b的最長公共子串行 子串行不要求是連續的 比如兩個串為 abcicba abdkscab ab是兩個串的子串行,abc也是,abca也是,其中abca是這兩個字串最長的子串行。輸入 第1行 字串a 第2行 字串b a,b的長度 1000 輸出 輸出最長的子串行,如果有多個,...

51NOD 最長公共子串行問題

最長公共子串行問題就是求序列a a1,a2,an,和b b1,b2,bm,的乙個最長公共子串行。因為最長公共子串行不唯一,讓我們把問題簡化,如何求出兩個序列的最長公共子串行長度呢?你首先能想到的恐怕是暴力列舉?那我們先來看看 序列a有 2 n 個子序列,序列b有 2 m 個子序列,如果任意兩個子串行...