bzoj1012 [JSOI2008]最大数maxnumber

现在请求你维护一个数列,要求提供以下两种操作: 1、 查询操作。语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值。限制:L不超过当前数列的长度。 2、 插入操作。语法:A n 功能:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取模,将所得答案插入到数列的末尾。限制:n是非负整数并且在长整范围内。注意:初始时数列是空的,没有一个数。

Input

第一行两个整数,M和D,其中M表示操作的个数(M <= 200,000),D如上文中所述,满足(0

Output

对于每一个查询操作,你应该按照顺序依次输出结果,每个结果占一行。

Sample Input

5 100
A 96
Q 1
A 97
Q 1
Q 2

Sample Output

96
93
96
 
这是单调栈的基础应用,模板题,当然单调队列也可以过。
标号+二分查找,就可以了。
 1 //单调栈 
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<algorithm>
 5 #include<cstdio>
 6 #include<cstring>
 7 #define N 200007
 8 using namespace std;
 9 
10 int n,d,t;
11 int top,len,a[N],num[N];
12 char ch[2];
13 
14 int main()
15 {
16     int x;
17     scanf("%d%d",&n,&d);
18     while(n--)
19     {
20         scanf("%s%d",ch,&x);
21         if(ch[0]=='A')
22         {
23             x=(x+t)%d;
24             num[++len]=x;
25             while(top&&num[a[top]]<=x)top--;
26             a[++top]=len;      
27         }
28         else
29         {
30             int y=lower_bound(a+1,a+top+1,len-x+1)-a;
31             t=num[a[y]];
32             printf("%d\n",t=num[a[y]]);
33         }
34     }
35 }
36 
37 //单调队列
38 #include<iostream>
39 #include<cstdio>
40 #include<algorithm>
41 #include<cstdio>
42 #include<cstring>
43 using namespace std; 
44 int m,d,a[200001],t,max[200001],l=0,p;
45 char q[1];
46 int main()
47 {
48     scanf("%d%d",&m,&d);
49     while (m--)
50     {
51         scanf("%s%d",q,&p);
52         if(q[0]=='A')
53         {
54             a[++t]=(l+p)%d;
55             for(int i=t;i;i--)
56                 if(max[i]<a[t])max[i]=a[t];
57                 else break;
58         }
59         else printf("%d\n",l=max[t-p+1]);
60     }
61 } 

 

 
posted @ 2017-09-24 20:16  Kaiser-  阅读(115)  评论(0编辑  收藏  举报