[AHOI2006]editor (SplayTree)

来源:互联网 发布:apache poi pdf 编辑:程序博客网 时间:2024/06/14 05:37

[AHOI2006]editor (SplayTree)

分析:都是基本的SplayTree操作,可以根据前一道题的代码构建这道题的函数.

 * 六种操作

 * Move k : 将光标移到到第k个字符之后,k=0则移到到最前面

 * Insert nS  :在光标后插入长度为n的字符串S

 * Delete n :删除光标后的n个字符

 * Rotate n:反转光标后的n个字符

 * Get:输出光标后的一个字符,光标位置不变

 * Prev : 光标前移一个字符

 * Next : 光标后移一个字符

 * 用一个变量记录光标的位置,Move , Prev , Next直接改变光标变量即可

 * Insert:插入操作,旋转之后插入到根的右孩子的左子树

 * Delete :Delete操作,删除右孩子的左子树

 * Rotate : 经典操作,区间反转,通过一个延迟标记记录

 * Get : 得到光标位置的后继,Get_Kth

AC代码:

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define Key_Value ch[ch[root][1]][0]const int maxn=1024*1024*2;int pre[maxn],size[maxn],ch[maxn][2],rev[maxn],root,tot1;char key[maxn];int pos;//pos表示光标当前所在缝隙的前一个字符的位置int s[maxn],tot2;char str[maxn];void New_Node(int &r,int fa,char c){    if(tot2) r=s[tot2--];    else r=++tot1;    key[r]=c;    pre[r]=fa;    size[r]=1;    rev[r]=ch[r][0]=ch[r][1]=0;}void Update_Rev(int r){    if(r==0)return ;    swap(ch[r][0],ch[r][1]);    rev[r]^=1;}void Push_Down(int r){    if(rev[r])    {        Update_Rev(ch[r][0]);        Update_Rev(ch[r][1]);        rev[r]=0;    }}void Push_Up(int r){    size[r]=1+size[ch[r][0]]+size[ch[r][1]];}void Build(int &x,int l,int r,int fa){    if(l>r) return ;    int mid=(l+r)/2;    New_Node(x,fa,str[mid]);    Build(ch[x][0],l,mid-1,x);    Build(ch[x][1],mid+1,r,x);    Push_Up(x);}void init(){    pos=root=tot1=tot2=0;    pre[root]=ch[root][0]=ch[root][1]=size[root]=rev[root]=0;    New_Node(root,0,' ');    New_Node(ch[root][1],root,' ');    Push_Up(root);}void Rotate(int x,int kind){    int y=pre[x];    Push_Down(y);    Push_Down(x);    ch[y][!kind]=ch[x][kind];    pre[ch[x][kind]]=y;    if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y] = x;    pre[x]=pre[y];    ch[x][kind]=y;    pre[y]=x;    Push_Up(y);}void Splay(int r,int goal){    while(pre[r]!=goal)    {        if(pre[pre[r]]==goal)            Rotate(r,ch[pre[r]][0]==r);        else        {            int y=pre[r];            int kind= ch[pre[y]][0]==y;            if(ch[y][kind]==r)            {                Rotate(r,!kind);                Rotate(r,kind);            }            else            {                Rotate(y,kind);                Rotate(r,kind);            }        }    }    Push_Up(r);    if(goal==0) root=r;}int Get_Kth(int r,int k){    Push_Down(r);    int t=size[ch[r][0]];    if(t+1==k) return r;    else if(k<=t) return Get_Kth(ch[r][0],k);    else return Get_Kth(ch[r][1],k-t-1);}int Get_Min(int r){    Push_Down(r);    while(ch[r][0])    {        r=ch[r][0];        Push_Down(r);    }    return r;}int Get_Max(int r){    Push_Down(r);    while(ch[r][1])    {        r=ch[r][1];        Push_Down(r);    }    return r;}//下面是本题的操作函数了void INSERT(int len){    Splay(Get_Kth(root,pos+1),0);    Splay(Get_Min(ch[root][1]),root);    Build(Key_Value,0,len-1,ch[root][1]);    Push_Up(ch[root][1]);    Push_Up(root);}void erase(int r){    if(r)    {        s[++tot2]=r;        erase(ch[r][0]);        erase(ch[r][1]);    }}void DELETE(int len){    Splay(Get_Kth(root,pos+1),0);    Splay(Get_Kth(root,pos+len+2),root);    erase(Key_Value);    Key_Value=0;    Push_Up(ch[root][1]);    Push_Up(root);}void REVERSE(int len){    Splay(Get_Kth(root,pos+1),0);    Splay(Get_Kth(root,pos+len+2),root);    Update_Rev(Key_Value);    Push_Up(ch[root][1]);    Push_Up(root);}void GET(){    printf("%c\n",key[Get_Kth(root,pos+2)]);}int main(){    int n,x;    char op[20];    while(scanf("%d",&n)==1)    {        init();        while(n--)        {            scanf("%s",op);            if(op[0]=='I')            {                scanf("%d%*c",&x);                gets(str);                INSERT(x);            }            else if(op[0]=='M')            {                scanf("%d",&x);                pos=x;            }            else if(op[0]=='D')            {                scanf("%d",&x);                DELETE(x);            }            else if(op[0]=='R')            {                scanf("%d",&x);                REVERSE(x);            }            else if(op[0]=='G')            {                GET();                //printf("%c\n",key[Get_Kth(root,pos+2)]);            }            else if(op[0]=='P') pos--;            else pos++;        }    }    return 0;}


0 0
原创粉丝点击