1 Description
 2 现在请求你维护一个数列,要求提供以下两种操作: 1、 查询操作。语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值。限制:L不超过当前数列的长度。 2、 插入操作。语法:A n 功能:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取模,将所得答案插入到数列的末尾。限制:n是非负整数并且在长整范围内。注意:初始时数列是空的,没有一个数。
 3 
 4 Input
 5 第一行两个整数,M和D,其中M表示操作的个数(M <= 200,000),D如上文中所述,满足(0
 6 
 7 Output
 8 对于每一个查询操作,你应该按照顺序依次输出结果,每个结果占一行。
 9 
10 Sample Input
11 5 100
12 A 96
13 Q 1
14 A 97
15 Q 1
16 Q 2
17 Sample Output
18 96
19 93
20 96

单调栈解法:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstdio>
 5 using namespace std;
 6 int n,d,t;
 7 int top,len,a[200001],num[200001];
 8 int main()
 9 {
10     int x;char ch[1];
11     scanf("%d%d",&n,&d);
12     while(n--)
13     {
14               scanf("%s%d",ch,&x);
15               if(ch[0]=='A')
16               {
17                       x=(x+t)%d;
18                       num[++len]=x;//存储原始数据
19                       while(top&&num[a[top]]<=x)top--;// a[]数组维护单调减队列(a[]储存单调数列在原始数据的位置)
20                       a[++top]=len;      
21                       }
22               else{
23                   int y=lower_bound(a+1,a+top+1,len-x+1)-a;
24                   t=num[a[y]];
25                   printf("%d\n",t);
26               }
27           }
28     return 0;
29 }

解法二: 线段树。维护区间最大值;