CH134 雙端佇列 題解報告

2022-04-28 20:27:10 字數 1480 閱讀 2224

題目傳送門

【題目大意】

用若干個雙端佇列給$n$個整數排序,依次處理這$n$個數,對於每個數$a_i$,可以進行兩種操作:

1.新建乙個雙端佇列,並將$a_i$作為這個佇列中唯一的數

2.把$a_i$從已有佇列的隊頭或隊尾入隊

對所有的數處理完後,要求這些佇列能夠按照一定的順序連線起來,得到乙個非降的長度為$n$的序列,求最少需要多少個雙端佇列。

【思路分析】

我們把問題反過來思考,先把$n$個數從小到大排序,然後分成盡量少的幾段,對應原問題中的合法雙端佇列。

易知乙個結論,對於排序後每個位置的數原本的下標組成的序列$b$,如果一段滿足單谷性質(即先遞減後遞增),那麼這一段就對應原問題中的乙個合法雙端佇列。(遞減的一段相當於從隊頭插入,遞增的一段相當於從隊尾插入)

還要注意一點,就是如果存在相同的幾個數,那麼它們排序後的位置是隨機的,可以看成乙個整體來處理。如果這個整體中最小的下標大於前面的序列中最大的下標,那麼滿足遞增;如果這個整體中最大的下標小於前面的序列中最小的下標,那麼滿足遞減。

【**實現】

1 #include2 #include3 #include4 #include5 #include6

#define g() getchar()

7#define rg register

8#define go(i,a,b) for(rg int i=a;i<=b;i++)

9#define back(i,a,b) for(rg int i=a;i>=b;i--)

10#define db double

11#define ll long long

12#define il inline

13#define pf printf

14using

namespace

std;

15int

fr()

22while(ch>='

0'&&ch<='

9') w=(w<<1)+(w<<3)+ch-'

0',ch=g();

23return w*q;24}

25const

int n=200002;26

intn;

27struct

numberd[n];

30struct

linel[n];

33 il bool

cmp(number x,number y)

36int

main()50}

51bool now=0;rg int ans=1

;52 go(i,2

,num)

57else61}

62 pf("

%d\n

",ans);

63return0;

64 }

**戳這裡

雙端佇列 Acwing 134 雙端佇列

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

AcWing 134 雙端佇列

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

acwing 134 雙端佇列

把乙個陣列排序,必須使用雙端佇列,必須從1到n依次處理,問最少要多少個雙端佇列。和歸併一樣,在乙個佇列裡,按照陣列下標從1到n,把值大的往後扔,小的往前扔。這樣乙個佇列裡面,從前往後,下標肯定是先減後增的。並且 這些佇列也是有序的,也就是說,除了第乙個佇列,乙個佇列的最小值應該是比乙個佇列的最大值大...