http://www.lydsy.com/JudgeOnline/problem.php?id=1012
https://www.luogu.org/problem/show?pid=1198
经典老题现在才AC。。。
这题方法很多,有单调栈,有线段树,有树状数组……
我是用线段树写的
其实就是胜者树求区间最大
我们建一棵大小为m的线段树,每个节点赋值为-2^30,然后插入节点(其实就是修改)和询问都是模板了
#include<bits/stdc++.h>
#define ll long long
using namespace std;
char c[5];
ll m,d,q=0,n=0;
ll t[800001]={0},lt[800001],rt[800001];
inline void build(ll l,ll r,ll nod){
t[nod]=-1<<30;lt[nod]=l;rt[nod]=r;
if(l==r)return;
ll mid=(l+r)>>1;
build(l,mid,nod*2);
build(mid+1,r,nod*2+1);
}
inline void xg(int i,int p,int nod){
if(lt[nod]==i&&rt[nod]==i)t[nod]=p;
else{
ll mid=(lt[nod]+rt[nod])>>1;
if(i>mid)xg(i,p,nod*2+1);
else xg(i,p,nod*2);
t[nod]=max(t[nod*2],t[nod*2+1]);
}
}
inline ll s(int i,int j,int nod){
if(lt[nod]==i&&rt[nod]==j)return t[nod];
ll mid=(lt[nod]+rt[nod])>>1;
if(j<=mid)return s(i,j,nod*2);
if(i>=mid+1)return s(i,j,nod*2+1);
ll le=s(i,mid,nod*2),re=s(mid+1,j,nod*2+1);
return max(le,re);
}
int main()
{
scanf("%lld%lld",&m,&d);
build(1,m,1);
ll x;
for(int i=1;i<=m;i++){
scanf("%s",c);
scanf("%lld",&x);
if(c[0]=='A'){
n++;xg(n,(x+q)%d,1);
}else{
q=s(n-x+1,n,1);
printf("%lld\n",q);
}
}
return 0;
}