Description
现在请求你维护一个数列,要求提供以下两种操作: 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
A 96
Q 1
A 97
Q 1
Q 2
Sample Output
96
93
96
93
96
斯巴达…………
果真如黄巨大所说,学完splay之后看什么题都变成splay了。
原来想的是用splay支持插入+区间查询,后来发现根本不要那么麻烦。因外每次插入都在末尾,区间查询也只是一段后缀的最大值。感觉单调栈可做……
后来瞄了一眼题解,发现真是单调栈……
学着标程写了一个STL的lower_bound二分,感觉怪怪的
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<algorithm> #include<cstring> #define maxn 200005 using namespace std; int n,t,d,s,len,top; char ch[5]; int a[maxn]; int zhan[maxn]; int main() { scanf("%d%d",&n,&d); for (int i=1;i<=n;i++) { scanf("%s%d",ch,&s); if (ch[0]=='A') { s=(t+s)%d; a[++len]=s; while (top && a[zhan[top]]<=s) top--; zhan[++top]=len; }else if (ch[0]=='Q') { int pos = lower_bound(zhan+1,zhan+top+1,len-s+1)-zhan; printf("%d\n",t=a[zhan[pos]]); } } }
——by zhber,转载请注明来源