题目描述
现在请求你维护一个数列,要求提供以下两种操作:
1、 查询操作。
语法:Q L
功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值。
限制:L不超过当前数列的长度。
2、 插入操作。
语法:A n
功能:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取模,将所得答案插入到数列的末尾。
限制:n是整数(可能为负数)并且在长整范围内。
注意:初始时数列是空的,没有一个数。
分析
就是一个水的线段树。
一个小小的线段树就可以AC了。
但是,刷的意义在于,c++现在也有线段树的模板啦
ps:记得要换行。
code
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<string>
#include<algorithm>
using namespace std;
struct arr{
int x,y;
int mx;
}f[3000000];
int n,m;
int insert(int r,int x,int y,int add)//线段树修改操作。
{
if (f[r].mx<add) f[r].mx=add;
if ((f[r].x==x)&&(f[r].y==y)) return 0;
int mid=(f[r].x+f[r].y)/2;
if (y<=mid) insert(r*2,x,y,add);
else if (x>mid) insert(r*2+1,x,y,add);
else insert(r*2,x,mid,add),insert(r*2+1,mid+1,y,add);
}
int find(int r,int x,int y)//线段树查找。
{
if ((f[r].x==x)&&(f[r].y==y)) return f[r].mx;
int mid=(f[r].x+f[r].y)/2;
if (y<=mid) return find(r*2,x,y);
else if (x>mid) return find(r*2+1,x,y);
else return max(find(r*2,x,mid),find(r*2+1,mid+1,y));
}
int maketree(int r,int x,int y)//建树
{
f[r].x=x; f[r].y=y; f[r].mx=-2000000000;
if (x==y) return 0;
int mid=(x+y)/2;
maketree(r*2,x,mid),maketree(r*2+1,mid+1,y);
}
int main()
{
scanf("%d%d",&n,&m);
maketree(1,1,n+n);
int ans=0;
int longth=0;
for (int i=1;i<=n;i++)//输入和操作
{
char s;
cin>>s;
int ii;
scanf("%d",&ii);
if (s=='A')
{
ii+=ans;
ii=ii%m;
longth++;
insert(1,longth,longth,ii);
}
else
{
ans=find(1,longth-ii+1,longth);
printf("%d\n",ans);
}
}
}