书堆 Splay

题目描述

  在桌子上有一堆书N本。可以在这堆书上进行如下两种操作:
  1.在这堆书的顶端添加一本新书,其操作为ADD(S),S是书名;
  2.把最上面的k本书的放置顺序颠倒。例如k=3,假设前三本书依次是《呐喊》,《彷徨》《哈里.波特》,进行此操作后顺序从上到下就变成了《哈里.波特》《彷徨》《呐喊》。若这堆书不足k本,就把整堆书全部翻转过来。其操作为ROTATE。任一时刻书的总数不会超过1000000。所有的书名为长度不超过3的由大写字母组成的字符串。书名有可能重复,但仍表示不同的书。

题目大意

加点,翻转,询问最后的结果

数据范围

数据范围

样例输入

2 3 2
A
B
ADD(C)
ROTATE
ADD(D)

样例输出

D
A
C
B

解题思路

Splay暴力维护。

代码

#include <bits/stdc++.h>
#define Maxn 2000005
using namespace std;
char ss[55];
int LLen;
inline void HashBack(int x) {
    if(x>=729) {
        ss[++LLen]=char(x/729+'A'-1);
        HashBack(x%729);
        return;
    }
    if(x>=27) {
        ss[++LLen]=char(x/27+'A'-1);
        HashBack(x%27);
        return;
    }
    ss[++LLen]=char(x+'A'-1);
}
namespace IStream {
    const int LLL=1<<15;
    char buffer[LLL],*SSS,*TTT;
    char Get_Char() {
        if(SSS==TTT) {
            TTT=(SSS=buffer)+fread(buffer,1,LLL,stdin);
            if(SSS==TTT) return EOF;
        }
        return *SSS++;
    } int Getint() {
        char c;
        int re=0,f=1;
        for(c=Get_Char(); c<'0'||c>'9'; c=Get_Char())if(c=='-')f=-1;
        while(c>='0'&&c<='9')re=(re<<1)+(re<<3)+(c-'0'),c=Get_Char();
        return re*f;
    }
    bool Getstr() {
        LLen=0;
        char ch=Get_Char();
        while(!isalpha(ch))ch=Get_Char();
        if(ch=='R'){
            Get_Char();
            Get_Char();
            Get_Char();
            Get_Char();
            Get_Char();
            Get_Char();
            return 1;
        }
        while(ch!='(')ch=Get_Char();
        while((ch=Get_Char())!=')')ss[++LLen]=ch;
        return 0;
    }
    void Get() {
        LLen=0;
        char ch=Get_Char();
        while(!isalpha(ch))ch=Get_Char();
        while(isalpha(ch))ss[++LLen]=ch,ch=Get_Char();
    }
}
class OStream {
    private:
        static const int LLL=1<<20;
        char staack[21];
        int topp;
        char buffer[LLL],*SSS;
    public:
        OStream() {
            SSS=buffer;
        } void Putint(int x,int flag) {
            bool fl=false;
            if(flag==1) staack[++topp]=' ';
            if(flag==2) staack[++topp]='\n';
            if(x<0) x=-x,fl=true;
            if(!x) staack[++topp]='0';
            while(x)staack[++topp]=x%10+'0',x/=10;
            if(fl)staack[++topp]='-';
            while(topp) {
                if(SSS==buffer+LLL-1) {
                    fwrite(buffer,1,SSS-buffer,stdout);
                    SSS=buffer;
                }*SSS++=staack[topp--];
            }
        } void Putstr(){
            staack[++topp]='\n';
            for(int i=LLen;i;i--)
                staack[++topp]=ss[i];
            while(topp){
                if(SSS==buffer+LLL-1){
                    fwrite(buffer,1,SSS-buffer,stdout);
                    SSS=buffer;
                }*SSS++=staack[topp--];
            }
        }~OStream() {
            fwrite(buffer,1,SSS-buffer,stdout);
            *SSS=0;
        }
} os;
int a[Maxn];
struct splay {
    int f[Maxn],son[Maxn][2],vl[Maxn],size[Maxn],lazy[Maxn],root,cnt;
    inline void PushUp(int x) {
        if(x)size[x]=size[son[x][0]]+size[son[x][1]]+1;
    }
    inline void PushDown(int x) {
        if(lazy[x]) {
            lazy[son[x][0]]^=1;
            lazy[son[x][1]]^=1;
            swap(son[x][0],son[x][1]);
            lazy[x]=0;
        }
    }
    inline 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(sn);
        PushUp(fa);
        PushUp(x);
    }
    inline void Splay(int x,int goal) {
        if(x==goal)return;
        while(f[x]!=goal) {
            if(f[f[x]])PushDown(f[f[x]]);
            if(f[x])PushDown(f[x]);
            if(x)PushDown(x);
            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;
    }
    inline int Select(int pos) {
        if(!pos)return 0;
        int p=root;
        PushDown(p);
        while(size[son[p][0]]+1!=pos) {
            if(pos<=size[son[p][0]])p=son[p][0];
            else pos-=size[son[p][0]]+1,p=son[p][1];
            PushDown(p);
        }
        return p;
    }
    inline void Insert(int pos,int val) {
        int u=Select(pos+1),v=Select(pos+2);
        Splay(u,0);
        Splay(v,u);
        PushDown(u);
        PushDown(v);
        size[++cnt]=1;
        vl[cnt]=val;
        f[cnt]=v;
        son[v][0]=cnt;
        PushUp(v);
        PushUp(u);
    }
    inline void Rev(int L,int r) {
        int u=Select(L),v=Select(r+2);
        Splay(u,0);
        Splay(v,u);
        lazy[son[v][0]]^=1;
    }
    inline void Build(int L,int r,int fa) {
        int mid=(L+r)/2;
        if(L>r)return;
        if(L!=r)Build(L,mid-1,mid),Build(mid+1,r,mid);
        vl[mid]=a[mid-1];
        PushUp(mid);
        f[mid]=fa;
        son[fa][mid>=fa]=mid;
    }
    inline void Init(int &n) {
        Build(1,n+2,0);
        root=n+3>>1;
        cnt=n+2;
    }
    void DEBUG(int x,int dep){
        if(!x)return;
        PushDown(x);
        DEBUG(son[x][0],dep+1);
        if(vl[x]){
            LLen=0;
            HashBack(vl[x]);
            os.Putstr();    
        }
        DEBUG(son[x][1],dep+1);
    }
} Solver;
inline int Hash() {
    if(LLen==3)return (ss[1]-'A'+1)*27*27+(ss[2]-'A'+1)*27+ss[3]-'A'+1;
    if(LLen==2)return (ss[1]-'A'+1)*27+(ss[2]-'A'+1);
    if(LLen==1)return (ss[1]-'A'+1);
}
int main() {
    int n,m,k,N;
    N=n=IStream::Getint();
    m=IStream::Getint();
    k=IStream::Getint();
    for(int i=1; i<=n; i++) {
        IStream::Get();
        a[i]=Hash();
    }
    Solver.Init(n);
    int L=0;
    for(register int i=1;i<=m;i++){
        bool ret=IStream::Getstr();
        if(ret)L^=1;
        else {
            if(L){
                Solver.Rev(1,min(n,k));
                L=0;
            }
            Solver.Insert(0,Hash()),n++;
        }
    }
    if(L)Solver.Rev(1,min(n,k));
    Solver.DEBUG(Solver.root,0);
    return 0;
}

转载于:https://www.cnblogs.com/Cedric341561/p/6811000.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值