【數據結構】維護隊列

T69293 維護隊列

題目描述

Alice 給 Bob 佈置了不少工做,他忙的不可開交,決定按照「先進先出(FIFO)」的順序依次處理這些工做。可是處理過程當中,Bob 意識到這種順序可能不是最優的,所以他會選擇性的把某些工做延後。html

抽象來講,你須要維護一個隊列,支持三種操做:c++

操做一:1 v,在隊尾加入一個價值爲 v 的任務。數組

操做二:2,若是當前隊列爲空,輸出 -1;不然輸出隊頭任務的價值,並將隊頭彈出。ide

操做三:3,若是當前隊列爲空,則不進行任何操做;不然將隊列中價值最小的任務挪到隊尾,保證沒有價值相等的任務。spa

輸入輸出格式

輸入格式:code

 

第一行一個整數 n,表示操做個數。htm

接下來 n 行,每行一個或兩個整數,格式如上。blog

 

輸出格式:隊列

 

對於每一個操做 2,輸出答案。it

 

輸入輸出樣例

輸入樣例#1: 
5
1 1
1 2
2
2
2
輸出樣例#1: 
1
2
-1
輸入樣例#2: 
6
1 1
1 2
3
2
2
2
輸出樣例#2: 
2
1
-1

【題解】:
聽過講解以後,發現這個想法很是有趣。
其實Push,Pop通常隊列均可以維護,可是對於Mov操做就須要你們開動一下腦筋了。
其實Mov不必定須要移動。須要的是標記,最小值標記,而後用Set來查找最小值的位置,
而後Push進去的歷史編號。
獲得的Val[No] 用數組來保存歷史編號的值便可。
Push( ) 進入隊列不單單是隊列,還有Set。
Pop( ) 彈出時注意,有些用Mov標記的可能出如今隊頭,記得要把它彈出。
Mov( )操做涉及到兩個問題。
第一個:用Set的頭元素即爲最小值的,同時Set存的是pair類型,
第一關鍵字是:權值,val,第二關鍵字爲:歷史編號 ,No
Set直接找到對應的歷史編號進行標記。
同時在Set刪除,而後對於隊列來講,從新Push進去一個val值。

附上代碼:
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N = 3e5+100;
 4 queue <int> Q ;
 5 set< pair<int,int> > S;
 6 int cur ,val[N] , top ;
 7 bool deleted[N];
 8 void push( int v ){
 9     cur ++ ;
10     val[cur] = v;
11     Q.push(cur);
12     S.insert( make_pair(v,cur) );
13 }
14 int pop(){
15     if( S.empty() ) return -1;
16     while( deleted[Q.front()] ){
17         Q.pop();
18     }
19     int ret = Q.front();
20     Q.pop();
21     S.erase( make_pair(val[ret],ret) );
22     return val[ret];
23 }
24 void mov(){
25     if( S.empty() ) return ;
26     deleted[S.begin()->second] = true ;
27     push(val[S.begin()->second]);
28     S.erase( S.begin() );
29 }
30 int main()
31 {
32     int n,opt,v;
33     scanf("%d",&n);
34     while(n--){
35         scanf("%d",&opt);
36         if( opt == 1 ){
37             scanf("%d",&v);
38             push(v);
39         }else if( opt == 2 ){
40             printf("%d\n",pop());
41         }else{
42             mov();
43         }
44     }
45     return 0;
46 }
維護隊列
相關文章
相關標籤/搜索