1. 程式人生 > >NEFU-大二大三訓練賽17C-最大值

NEFU-大二大三訓練賽17C-最大值

Description

現在請求你維護一個數列,要求提供以下兩種操作:1、 查詢操作。語法:Q L 功能:查詢當前數列中末尾L個數中的最大的數,並輸出這個數的值。
限制:L不超過當前數列的長度。2、 插入操作。語法:A n 功能:將n加上t,其中t是最近一次查詢操作的答案(如果還未執行過查詢操作,則t=0),
並將所得結果對一個固定的常數D取模,將所得答案插入到數列的末尾。限制:n是非負整數並且在長整範圍內。注意:初始時數列是空的,沒有一個數。

Input

第一行兩個整數,M和D,其中M表示操作的個數(M <= 200,000),D如上文中所述,滿足D在longint內。接下來M行,查詢操作或者插入操作。

Output

對於每一個詢問操作,輸出一行。該行只有一個數,即序列中最後L個數的最大數。

Sample Input

5 100

A 96

Q 1

A 97

Q 1

Q 2

Sample Output

96

93

96


解題思路:
  創立陣列進行模擬優先佇列的操作,這道題每次查詢最大值只是在隊尾的一段長度中查詢。
  所以當在佇列尾部加入值時,要把佇列尾部比此值小的值全部pop出來,同時記錄下這個值的插入編號。
  最後在查詢的時候用二分查詢編號。
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 
 5 using namespace std;
 6 
 7 const int maxn=2e5+10;
 8 
 9 int n,tail,head,m,mod;
10 int q[maxn],id[maxn];
11 
12 void add(int x)
13 {
14     while(q[tail]<=x&&tail)tail--;
15     q[++tail]=x;id[tail]=++n;
16 } 17 18 int qurey(int x) 19 { 20 int l=n-x+1; 21 int k=lower_bound(id+head,id+tail+1,l)-id; 22 return q[k]; 23 } 24 25 int main() 26 { 27 scanf("%d %d",&m,&mod); 28 int last=0; 29 head=1;tail=0; 30 while(m--) 31 { 32 char str[2]; 33 int a; 34 scanf("%s%d",str,&a); 35 if(str[0]=='A') 36 add((a+last)%mod); 37 else 38 { 39 printf("%d\n",last=qurey(a)); 40 } 41 } 42 return 0; 43 }
View Code