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行,查询操作或者插入操作。
Solution
操作全部都是往最后插数,并且只需要维护后缀最大值所以……
(想到什么奇奇怪怪的数据结构的八成是数据结构学傻了=w=)
用一个单调栈维护最大值就好了,弹出条件是栈顶不比当前的元素大。查询操作在栈中二分。
#include<stdio.h>
int n,mod,t,e,tot,p[200002],l,r,mid,k;
long long a[200002];
int main()
{
scanf("%d%d",&n,&mod);
a[0]=2333333333333333333LL;
while (n--)
{
char ch=getchar();
while (ch!='A' && ch!='Q') ch=getchar();
scanf("%d",&k);
if (ch=='A')
{
k=((long long)k+t) % mod;
while (a[e]<=k) e--;
a[++e]=k;
p[e]=++tot;
}
else
{
for (l=0,r=e,mid=e>>1;l<r;mid=(l+r)>>1) if (p[mid]<tot-k+1) l=mid+1;
else r=mid;
printf("%d\n",t=(l==0?0:(int)a[l]));
}
}
}