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
",last=qurey(a));
40         }
41     }
42     return 0;
43 }
View Code
 
原文地址:https://www.cnblogs.com/wyhbadly/p/10037652.html