跳跃的小怪兽 Splay

来源:互联网 发布:手机sd数据恢复软件 编辑:程序博客网 时间:2024/04/29 13:00

题目描述

  n个小怪兽站成一行跳来跳去。每次跳跃操作是以下两种形式之一:
a L b:从左到右第a个小怪兽跳过它左边的b个小怪兽,然后落地。
a D b:从左到右第a个小怪兽跳过它右边的b个小怪兽,然后落地。
小怪兽有身高差异,因此在跳跃时需要注意不要碰到其他小怪兽的头。具体来说,每次跳跃的高度等于越过的所有小怪兽的身高的最大值。
你的任务是计算出每次跳跃的高度。

题目大意

单点删除,单点插入,求区间最大值。

数据范围

n,j<=10000

样例输入

9 3
5 3 8 4 9 3 7 4 2
2 D 3
8 L 2
5 D 2

样例输出

9
7
4

解题思路

Splay维护区间,每个点有一个Max和vl属性,分别为当前区间最大值和当前点的值。
注意重新insert一个点后,这个点要设置Size为1,Max=vl。

代码

#include <algorithm>#include <iostream>#include <cstring>#include <cstdlib>#include <cstdio>#include <cmath>#define Maxn 200005using namespace std;inline int Getint(){int x=0,f=1;char ch=getchar();while('0'>ch||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}inline char Getch(){char ch=getchar();while(!isalpha(ch))ch=getchar();return ch;}int a[Maxn];struct splay{    int f[Maxn],son[Maxn][2],vl[Maxn],Max[Maxn],Size[Maxn],root,cnt;    int GetSize(int x){        return Size[son[x][0]]+Size[son[x][1]]+1;    }    void PushUp(int x){        Max[x]=vl[x];        Max[x]=max(Max[son[x][0]],Max[x]);        Max[x]=max(Max[son[x][1]],Max[x]);        Size[x]=GetSize(x);    }    void Rotate(int x){        int fa=f[x],gr=f[fa],s=son[fa][1]==x,sn=son[x][!s];        son[f[x]=gr][son[gr][1]==fa]=x;        son[f[fa]=x][!s]=fa;        son[f[sn]=fa][s]=sn;        PushUp(fa);        PushUp(x);    }    void Splay(int x,int goal){        if(x==goal)return;        while(f[x]!=goal){            if(f[f[x]]!=goal&&(son[f[f[x]]][1]==f[x])==(son[f[x]][1]==x))Rotate(f[x]);            Rotate(x);        }        if(!goal)root=x;    }    int Select(int x){        if(!x)return 0;        int p=root;        while(Size[son[p][0]]+1!=x){            if(x<=Size[son[p][0]])p=son[p][0];            else x-=Size[son[p][0]]+1,p=son[p][1];        }        PushUp(x);        return p;    }    int Delete(int pos){        int u=Select(pos),v=Select(pos+2);        Splay(u,0);        Splay(v,u);        f[son[v][0]]=0;        int ret=vl[son[v][0]];        son[v][0]=0;        Size[son[v][0]]=0;        PushUp(v);        PushUp(u);        return ret;    }    void Insert(int pos,int val){        int u=Select(pos+1),v=Select(pos+2);        Splay(u,0);        Splay(v,u);        vl[++cnt]=val;        Max[cnt]=val;        son[cnt][0]=son[cnt][1]=0;        Size[cnt]=1;        f[cnt]=v;        son[v][0]=cnt;        PushUp(v);        PushUp(u);    }    int Ask(int L,int r){        int u=Select(L),v=Select(r+2);        Splay(u,0);        Splay(v,u);        return Max[son[v][0]];    }    void Build(int L,int r,int fa){        if(L>r)return;        int mid=(L+r)/2;        if(L==r){            Max[mid]=a[mid-1];            Size[mid]=1;            son[mid][0]=son[mid][1]=0;        }        else Build(L,mid-1,mid),Build(mid+1,r,mid);        f[mid]=fa;        vl[mid]=a[mid-1];        PushUp(mid);        son[fa][mid>=fa]=mid;    }}Solver;int main(){    int n=Getint(),q=Getint();    for(int i=1;i<=n;i++)a[i]=Getint();    Solver.Build(1,n+2,0);    Solver.root=n+3>>1;    Solver.cnt=n+2;    while(q--){        int pos=Getint();        char ch=Getch();        int Len=Getint();        if(ch=='L')cout<<Solver.Ask(pos-Len,pos-1)<<"\n";        if(ch=='D')cout<<Solver.Ask(pos+1,pos+Len)<<"\n";        int val=Solver.Delete(pos);        if(ch=='D')Solver.Insert(pos+Len-1,val);        if(ch=='L')Solver.Insert(pos-Len-1,val);    }    return 0;}
0 0
原创粉丝点击