雙端佇列排序 解題報告

2021-09-25 09:12:51 字數 2091 閱讀 7478

sherry現在碰到了乙個棘手的問題,有n個整數需要排序。 sherry手頭能用的工具就是若干個雙端佇列。 她需要依次處理這n個數,對於每個數,sherry能做以下兩件事: 1.新建乙個雙端佇列,並將當前數作為這個佇列中的唯一的數; 2.將當前數放入已有的佇列的頭之前或者尾之後。 對所有的數處理完成之後,sherry將這些佇列排序後就可以得到乙個非降的序列。

第一行包含乙個整數n,表示整數的個數。接下來的n行每行包含乙個整數di,其中di表示所需處理的整數。

其中只包含一行,為sherry最少需要的雙端佇列數。

6 3 6 0 9 6 3

100%的資料中n≤200000。

1.這道題雖然叫做雙端佇列,但是如果要使用deque(雙端佇列)來解的話那麼只會gg,重要的是理解deque的特性只能在對頭或隊尾進行增刪。

2.觀察這道題的資料規模,發現是兩萬,如果演算法是o(n^2)的話那麼就直接gg了,如果是o(n logn),在每一次操作的比較多的話,那麼也會超時,所以得用o(n)的演算法qwq。

3.如何在只掃瞄一遍的情況下ac這道題,首先我們要排除掉模擬的方法,因為模擬的話鐵定超時,那麼怎麼辦?尋求乙個單個雙端佇列的本質:1.它是乙個單調的佇列,是公升序(非降序);2.所有佇列合起來,會得到乙個更大的單調佇列。這很像乙個排序的思想,而將多個有序佇列合併成乙個更大的有序佇列,這不正是大名鼎鼎的合併排序了嗎?

4.現在問題已經被簡化了,我們只需要求出這次的合併排序中,最少會被分成多少個有序的小組就對了。(注意:小組之間有時是可以合併的,例如[1,2,3],可以和[5,4,3]合併為[1,2,3,3,4,5])

5.如何在常數時間內解決這道題呢?我們可以先得到已經排好序的有序佇列,然後再與這個序列進行對比。

最開始的時候數列是 3 6 0 9 6 3

我們最後會得到的序列是 9 6 6 3 3 0

去掉重複的值 9 6 3 0

發現9和6在一起,6和3在一起,3和0在一起

拆分我們現在的序列 [3 6] [0 9] [6 3];

合併 -> [3 6 9] [0 3 6]

神奇的事情發生了,我們居然得到了樣例的答案!

但是這還沒完,時間複雜度,還不夠,離答案只剩一點點了!

這樣雖然大大簡化了難度和時間複雜度(相對於模擬),但是仍不足以支援我們ac,因為得到臨近順序之後再乙個個比較的工作量是巨大的,有沒有什麼辦法可以讓這個佇列的合併從一開始就決定了?亦或是根本就不知道它怎麼合併就可以得到答案?蒟蒻的我想不出後者,所以只能絞盡腦汁在前者上面做功夫。

----------

由於排序的是數字的值,我們可以反過來想,我們要幹的事就是要在這個值裡面找到可以相呼應的區間,那麼在排序的時候就得存下它的下標(序號)num,在重新掃瞄已經排好的序列的時候,就可以直接找掃瞄序列中下標的『拐點』,也就是單調性發生改變的點。因為陣列下標(num)代表的是這個數在序列中的位置,並且我們掃瞄的是已經排好的序列,那麼在同乙個單調的序列中,下標單調性改變的話就必然排不起來那麼就需要另乙個佇列。

題目說道這裡已經很清楚了,下面直接上**~~!

#include

#include

#include

using

namespace std;

const

int maxn=

2e5+10;

const

int inf =

2e9;

int ans =1;

int f =

1,noww=inf;

struct node

s[maxn]

;bool

cmp(node x, node y)

intmain()

sort

(s +

1, s + n +

1, cmp)

;for

(int i =

1; i <= n;)}

else

} i = j+1;

} cout

}

佇列 雙端佇列

1.佇列 佇列是遵循先進先出 fifo,也稱為先來先服務 原則的一組有序的項。佇列在尾部新增新 元素,並從頂部移除元素。最新新增的元素必須排在佇列的末尾 class queue 向佇列新增元素 enqueue element 檢查佇列是否為空並獲取它的長度 isempty 從佇列移除元素 deque...

CH134 雙端佇列 題解報告

題目傳送門 題目大意 用若干個雙端佇列給 n 個整數排序,依次處理這 n 個數,對於每個數 a i 可以進行兩種操作 1.新建乙個雙端佇列,並將 a i 作為這個佇列中唯一的數 2.把 a i 從已有佇列的隊頭或隊尾入隊 對所有的數處理完後,要求這些佇列能夠按照一定的順序連線起來,得到乙個非降的長度...

雙端佇列 Acwing 134 雙端佇列

達達現在碰到了乙個棘手的問題,有n個整數需要排序。達達手頭能用的工具就是若干個雙端佇列。她從1到n需要依次處理這n個數,對於每個數,達達能做以下兩件事 1 新建乙個雙端佇列,並將當前數作為這個佇列中的唯一的數 2 將當前數放入已有的佇列的頭之前或者尾之後。對所有的數處理完成之後,達達將這些佇列按一定...