Description
n个小怪兽站成一行跳来跳去。每次跳跃操作是以下两种形式之一:
a L b:从左到右第a个小怪兽跳过它左边的b个小怪兽,然后落地。
a D b:从左到右第a个小怪兽跳过它右边的b个小怪兽,然后落地。
小怪兽有身高差异,因此在跳跃时需要注意不要碰到其他小怪兽的头。具体来说,每次跳跃的高度等于越过的所有小怪兽的身高的最大值。
你的任务是计算出每次跳跃的高度。
Input
输入第一行包含两个整数n(2<=n<=100,000), J(1<=J<=100,000),表示小怪兽的个数和跳跃的个数。
第二行有n个小于100,000的正整数,即各个小怪兽的身高(从左到右)。
以下J行每行描述一次跳跃(按照实际跳跃顺序排列),格式为”a L b”或者”a D b”,含义如图所述。跳跃总是合法的,即往左跳时,左数第a个小怪兽左边至少有b个小怪兽;往右跳时,左数第a个小怪兽右边至少有b个小怪兽。
Output
对于每次跳跃,输出一行,包含本次跳跃的高度。
Sample Input
9 3
5 3 8 4 9 3 7 4 2
2 D 3
8 L 2
5 D 2
Sample Output
9
7
4
Hint
【样例解释】
第一次跳:5 3 8 4 9 3 7 4 2 -> 5 8 4 9 3 3 7 4 2,max{8,4,9}=9
第二次跳:5 8 4 9 3 3 7 4 2 -> 5 8 4 9 3 4 3 7 2,max{3,7}=7
第三次跳:5 8 4 9 3 4 3 7 2 -> 5 8 4 9 4 3 3 7 2,max{4,3}=4
删除,插入,区间查询。
再一个一道题一整天系列,经过changxv大佬的提醒,发现我之前的插入,删除操作写的都很蠢,而且对于这道题竟然会挂掉,原来合理利用BST中序的性质(参见文艺平衡树),可以很好地实现插入和删除。
我们要在x位置插入,现将x-1转到根,再将x转到x-1的右儿子,由中序遍历性质,x没有左儿子,我们只需将新建节点作为x的左儿子,新节点就成为了序列中的x位置,而x就变成了x+1位置。
删除同理。
#include<bits/stdc++.h>
using namespace std;
inline int Getint(){register int re=0,f=1;register char c;while(c=getchar(),(c>='0'&&c<='9')^1)f=c^'-';while(re=(re<<1)+(re<<3)+(c^48),c=getchar(),(c>='0'&&c<='9'));return f?re:-re;}
inline char Getchar(){char c=getchar();while(c^'D'&&c^'L')c=getchar();return c;}
#define Inc(i,L,R) for(register int i=(L);i<=(R);++i)
#define Red(j,R,L) for(register int j=(R);j>=(L);--j)
const int N = 2e5+10;
int n,m,a[N/2];
struct Splay{
int k[N],Max[N],siz[N];
int rt,cnt,p[N],ch[N][2];
#define Ls(v) ch[v][0]
#define rs(v) ch[v][1]
inline void maintain(int x){
siz[x]=siz[Ls(x)]+siz[rs(x)]+1;
Max[x]=max(k[x],max(Max[Ls(x)],Max[rs(x)]));
}
inline int build(int L,int r){
if(L>r)return 0;
int x=++cnt,Mid=L+r>>1;
k[x]=Max[x]=a[Mid];
siz[x]=1;
Ls(x)=build(L,Mid-1);
rs(x)=build(Mid+1,r);
if(Ls(x))p[Ls(x)]=x;
if(rs(x))p[rs(x)]=x;
maintain(x);
return x;
}
inline void rot(int x){
int f=p[x],gf=p[f],type=rs(f)==x,son=ch[x][!type];
ch[p[son]=f][type]=son,maintain(f);
ch[p[f]=x][!type]=f,maintain(x);
ch[p[x]=gf][rs(gf)==f]=x;
}
inline void splay(int x,int goal){//旋转在目标的下面
while(p[x]^goal){
if((p[p[x]]^goal)&&((rs(p[p[x]])==p[x])==(rs(p[x])==x)))rot(p[x]);
rot(x);
}
if(!goal)rt=x;
}
inline int FindPos(int Size){
int x=rt;
while(1){
if(siz[Ls(x)]+1==Size)break;
if(Size>siz[Ls(x)]+1)Size-=siz[Ls(x)]+1,x=rs(x);
else x=Ls(x);
}
return x;
}
inline void Delete(int kp){
int L=FindPos(kp-1),r=FindPos(kp+1);
splay(L,0),splay(r,rt);
Ls(r)=0;
maintain(r),maintain(L);
}
inline void Insert(int kp,int v){
int L=FindPos(kp-1),r=FindPos(kp);
splay(L,0),splay(r,rt);
siz[++cnt]=1;
k[cnt]=Max[cnt]=v;
p[Ls(r)=cnt]=r;
maintain(cnt),maintain(r),maintain(L);
}
inline void update(int A,int b,bool opt){
int New,Tmpk;
if(opt==0){
int Ap=FindPos(A),bp=FindPos(A+b+1);
splay(Ap,0),splay(bp,rt);
cout<<Max[Ls(bp)]<<"\n";
New=A+b;
}else {
int Ap=FindPos(A-b-1),bp=FindPos(A);
splay(Ap,0),splay(bp,rt);
cout<<Max[Ls(bp)]<<"\n";
New=A-b;
}
Tmpk=k[FindPos(A)];
Delete(A);
Insert(New,Tmpk);
}
}sp;
inline void init(){
n=Getint(),m=Getint();
a[1]=-0x3f3f3f3f;//加哨兵
Inc(i,2,n+1)a[i]=Getint();
a[n+2]=-0x3f3f3f3f;
sp.rt=sp.build(1,n+2);
}
inline void solv(){
Inc(i,1,m){
int A=Getint();char c=Getchar();int b=Getint();
if(c=='D')sp.update(A+1,b,0);
else sp.update(A+1,b,1);
}
}
int main(){
init();
solv();
return 0;
}