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 }