[AHOI2006]文本编辑器editor (Splay tree)

来源:互联网 发布:网络代维管理系统下载 编辑:程序博客网 时间:2024/05/13 10:02

我感觉伸展树越来越模版了,没想到这么轻易的就过了。。。

把光标位置标记为pos

MOVE:pos++或者pos--

INSERT:把光标旋转至根部,然后把光标后一个字母旋转至根的右子树,然后把insert的内容插入到root的右子树的左子树

ROTATE:把光标旋转至根部,然后把光标后一个字母旋转至根的右子树,然后把rev[root10]取反

GET:得到光标位置的后继,可以GET_KTH后然后GET_NEXT,也可以直接旋转,或者旋转后GET_MIN

PREV,NEXT:都只需要改变光标位置变量

#include<stdio.h>#include<string.h>#include<algorithm>#include<iostream>#include<vector>using namespace std;#define maxn 5500000#define mem(a,b) memset(a,b,sizeof(a))#define root10 ch[ch[root][1]][0]#define root1 ch[root][1]int pre[maxn],ch[maxn][2],root,tot;int size[maxn];int rev[maxn];int key[maxn];int n;int pos;void Treaval(int x) {    if(x) {        Treaval(ch[x][0]);        printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,key = %2d \n",x,ch[x][0],ch[x][1],pre[x],size[x],key[x]);        Treaval(ch[x][1]);    }}void debug() {printf("%d\n",root);Treaval(root);}//以上Debugvoid init(){    root=tot=0;    mem(pre,0);    mem(ch,0);    mem(size,0);    mem(rev,0);    mem(key,0);}void newnode(int &x,char k,int father){    x=++tot;    pre[x]=father;    size[x]=1;    ch[x][0]=ch[x][1]=0;    rev[x]=0;    key[x]=k;}void push_down(int x){    if(rev[x])    {        rev[x]=0;        rev[ch[x][0]]^=1;        rev[ch[x][1]]^=1;        swap(ch[x][0],ch[x][1]);    }}void push_up(int x){    size[x]=size[ch[x][0]]+size[ch[x][1]]+1;}void rot(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);    push_up(x);}void splay(int x,int goal){    push_down(x);    while(pre[x]!=goal)    {        if(pre[pre[x]]==goal)        {            push_down(pre[x]);            push_down(x);            rot(x,ch[pre[x]][0]==x);        }        else        {            int y=pre[x];            push_down(pre[y]);            push_down(y);            push_down(x);            int kind=ch[pre[y]][0]==y;            if(ch[y][kind]==x)            {                rot(x,!kind);                rot(x,kind);            }            else            {                rot(y,kind);                rot(x,kind);            }        }    }    push_up(x);    if(goal==0)root=x;}void buildtree(int &x,int l,int r,int father,char str[]){    if(l>r)return ;    int mid=(l+r)/2;    newnode(x,str[mid],father);    buildtree(ch[x][0],l,mid-1,x,str);    buildtree(ch[x][1],mid+1,r,x,str);    push_up(x);}int get_kth(int x,int k){    push_down(x);    int p=size[ch[x][0]];    if(p+1==k)return x;    else if(k<=p)return get_kth(ch[x][0],k);    else get_kth(ch[x][1],k-p-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(char str[]){    int len=strlen(str);    int x=get_kth(root,pos);    //debug();   // cout<<x<<" "<<root<<endl;    splay(x,0);//cout<<"_-"<<endl;    int m=get_min(root1);    splay(m,root);    buildtree(root10,0,len-1,root1,str);}void del(int k){    int x=get_kth(root,pos);    splay(x,0);    int y=get_kth(root,pos+k+1);    splay(y,root);    pre[root10]=0;    root10=0;    push_up(root1);    push_up(root);}void revs(int k){    int x=get_kth(root,pos);    splay(x,0);    int y=get_kth(root,pos+k+1);    splay(y,root);    rev[root10]^=1;}int get_ans(){    int x=get_kth(root,pos);    splay(x,0);    int y=get_min(root1);    return key[y];}char str[maxn];int main(){    scanf("%d",&n);    init();    newnode(root,' ',0);    newnode(root1,' ',root);    pos=1;    int k;    while(n--){            scanf("%s",str);            if(str[0]=='I'){                scanf("%d",&k);                getchar();                gets(str);                insert(str);            }            else if(str[0]=='M'){                scanf("%d",&k);                pos=k+1;            }            else if(str[0]=='D'){                scanf("%d",&k);                del(k);            }            else if(str[0]=='R'){                scanf("%d",&k);                revs(k);            }            else if(str[0]=='G')                printf("%c\n",get_ans());            else if(str[0]=='P')                pos--;            else                pos++;        }    return 0;}


0 0