题目分析:
考虑线段树。我们先建一个叶子节点200000大的空树,用Cnt表示现在已经插入了Cnt个数,那么此时插入一个新的数就将第Cnt+1个叶子结点(从左往右)变为要插入的数,然后我们维护区间最大值;对于查询L-队列末的最大值,就相当于查询线段树上Cnt+1-L~Cnt的最大值,得解。
参考代码:
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define DB double
#define SG string
#define LL long long
#define Fp(A,B,C,D) for(A=B;A<=C;A+=D)
#define Fm(A,B,C,D) for(A=B;A>=C;A-=D)
#define Clear(A) memset(A,0,sizeof(A))
using namespace std;
const LL Max=2e5+5;
const LL Inf=1e18;
struct Node{
LL X,Y,Mx;
}Tree[Max<<2];
LL N,T,Mod,Cnt;
inline LL Read(){
LL X=0;char CH=getchar();bool F=0;
while(CH>'9'||CH<'0'){if(CH=='-')F=1;CH=getchar();}
while(CH>='0'&&CH<='9'){X=(X<<1)+(X<<3)+CH-'0';CH=getchar();}
return F?-X:X;
}
inline void Write(LL X){
if(X<0)X=-X,putchar('-');
if(X>9)Write(X/10);
putchar(X%10+48);
}
void MakeTree(LL P,LL X,LL Y){
Tree[P].X=X;Tree[P].Y=Y;Tree[P].Mx=-Inf;
if(X<Y){
MakeTree(P<<1,X,X+Y>>1);
MakeTree(P<<1|1,(X+Y>>1)+1,Y);
}
}
LL GetMax(LL P,LL X,LL Y){
LL I,J,K,Left=-Inf,Right=-Inf,Mid=Tree[P].X+Tree[P].Y>>1;
if(X<=Tree[P].X&&Tree[P].Y<=Y){
return Tree[P].Mx;
}
if(X<=Mid&&Y>=Tree[P].X){
Left=GetMax(P<<1,X,Y);
}
if(Y>Mid&&X<=Tree[P].Y){
Right=GetMax(P<<1|1,X,Y);
}
return max(Left,Right);
}
void Add(LL P,LL K,LL W){
if(Tree[P].X==Tree[P].Y){
Tree[P].Mx=W;
return;
}
if(Tree[P<<1].X<=K&&K<=Tree[P<<1].Y){
Add(P<<1,K,W);
}
if(Tree[P<<1|1].X<=K&&K<=Tree[P<<1|1].Y){
Add(P<<1|1,K,W);
}
Tree[P].Mx=max(Tree[P<<1].Mx,Tree[P<<1|1].Mx);
}
int main(){
LL I,J,K;
N=Read(),Mod=Read();
MakeTree(1,1,200000);
Fp(I,1,N,1){
char CH[2];
scanf("%s",CH);
if(CH[0]=='A'){
LL V=Read();++Cnt;
Add(1,Cnt,(V+T)%Mod);
} else {
LL L=Read();
T=GetMax(1,Cnt+1-L,Cnt);
Write(T);puts("");
}
}
return 0;
}