题目大意:维护一个数列,有两种操作:1、 查询当前数列中末尾L个数中的最大的数,并输出这个数的值。限制:L不超过当前数列的长度。2、插入操作:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取模,再将所得答插入到数列的末尾。初始时数列是空的,没有一个数。
思路:讲道理这道题用线段树肯定不是最好的(比如用栈),但是我现在在学线段树,就拿来练练手。线段树裸题,有单点加入、区间查询操作。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int da[800001];
void add(int l,int r,int x,int y,int cur)
{
da[cur]=max(da[cur],y);
if (l==r) return;
int mid=l+r>>1;
if (x>mid) add(mid+1,r,x,y,cur<<1|1);
else add(l,mid,x,y,cur<<1);
}
int ask(int L,int R,int l,int r,int cur)
{
if (L>=l && R<=r) return da[cur];
int mid=L+R>>1,ans=0;
if (l<=mid) ans=max(ans,ask(L,mid,l,r,cur<<1));
if (r>mid) ans=max(ans,ask(mid+1,R,l,r,cur<<1|1));
return ans;
}
int main()
{
int m,mod,ans=0,n=0;
scanf("%d%d",&m,&mod);
for (int i=1;i<=m;i++)
{
int l;
char ch=getchar();
while (ch<'A' || ch>'Z') ch=getchar();
scanf("%d",&l);
if (ch=='A')
{
n++;
int x=(l+ans)%mod;
add(1,m,n,x,1);
}
else printf("%d\n",ans=ask(1,m,n-l+1,n,1));
}
return 0;
}