传送门:BZOJ1012
比较naive的线段树或者说比较classical的单调队列。
线段树的做法就不讲了。
我们维护一个单调队列,满足升序排序,于是对任意i,如i>j且a[i]>a[j]则从队列中删除a[j]。
显然,队列操作的均摊复杂度为O(1)。
回答询问操作时我们二分即可。
代码上的小细节见下。
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int INF=0x3f3f3f3f;
struct Node{
int ord;
int w;
Node(){
ord=0;
w=0;
}
Node(int ord_,int w_){
ord=ord_;
w=w_;
}
};
Node da[200005];
int pos;
int n;
int D;
int op;
int Middle(int R)
{
int a=1,b=pos;
R=op-R+1;
while(a<b){
int mid=(a+b)/2;
if(da[mid].ord<R)
a=mid+1;
else
b=mid;
}
return a;
}
int Query(int R)
{
int i=Middle(R);
return da[i].w;
}
void Insert(int w,int num)
{
while(da[pos].w<w)
pos--;
da[++pos]=Node(num,w);
}
void Readdata()
{
freopen("loli.in","r",stdin);
scanf("%d%d\n",&n,&D);
}
void Solve()
{
da[0]=Node(0,INF);
pos=1;
int t=0,num=0;
for(int i=1;i<=n;i++){
char s,crash;
scanf("%c%c%d\n",&s,&crash,&num);
if(s=='Q')
printf("%d\n",t=Query(num));
else
Insert((t+num)%D,++op);
}
}
void Close()
{
fclose(stdin);
fclose(stdout);
}
int main()
{
Readdata();
Solve();
Close();
return 0;
}