BZOJ 1507 NOI 2003 Editor Splay

题目大意:维护一种数据结构,它可以:

1.移动光标

2.在光标之后插入一段字符串

3.删除光标之后的n个字符

4.输出光标之后的n个字符

5.移动光标


思路:Splay,没什么特别的。但是有几个需要注意的地方。1.题中说:delete操作不会越界。但是其实有可能会越界,比如样例就越界了。。

2.输出的时候一定不要偷懒。我刚开始写的时候就把输出写成nlogn输出的了,然后果断T了吗,我还以为是哪里死循环了,结果是这里被卡了!以后再也不偷懒随便加logn了。。。


CODE:


#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX (1 << 22|100)
using namespace std;

struct Complex{
    char c;
    int size;
    Complex *son[2],*father;

    void Combine(Complex *a,bool dir) {
        son[dir] = a;
        a->father = this;
    }  
    bool Check() {
    	return father->son[1] == this;
    }
    void PushUp() {
    	size = son[0]->size + son[1]->size + 1;
    }
}*nil = new Complex(),*root;

void Pretreatment();

Complex *BuildTree(int l,int r);
Complex *Kth(Complex *a,int k);
Complex *NewComplex(char val);

inline void Rotate(Complex *a,bool dir);
inline void Splay(Complex *a,Complex *aim);

void Print(Complex *a);

char src[MAX];
int asks,now;

char s[MAX];

int main()
{
    Pretreatment();
    cin >> asks;
    for(int x,i = 1;i <= asks; ++i) {
    	scanf("%s",s);
    	if(s[0] == 'M')	scanf("%d",&now);
    	else if(s[0] == 'I') {
    		scanf("%d",&x);
    		for(int j = 1;j <= x; ++j)
    			while(scanf("%c",&src[j]),src[j] < 32);
            Splay(Kth(root,now + 1),nil);
            Splay(Kth(root,now + 2),root);
            root->son[1]->Combine(BuildTree(1,x),false);
            root->son[1]->PushUp();
            root->PushUp();
    	}
    	else if(s[0] == 'D') {
    		scanf("%d",&x);
    		Splay(Kth(root,now + 1),nil);
    		Splay(Kth(root,min(root->size,now + x + 2)),root);
    		root->son[1]->son[0] = nil;
    		root->son[1]->PushUp();
    		root->PushUp();
    	}
    	else if(s[0] == 'G') {
    		scanf("%d",&x);
            Splay(Kth(root,now + 1),nil);
            Splay(Kth(root,min(now + x + 2,root->size)),root);
            Print(root->son[1]->son[0]);
            puts("");
    	}
    	else if(s[0] == 'P')	--now;
    	else					++now;
    }
    return 0;
}

void Pretreatment()
{
    root = BuildTree(1,2);
    root->father = nil;
    nil->father = nil->son[0] = nil->son[1] = nil;
    nil->size = 0;
}

Complex *BuildTree(int l,int r)
{
    if(l > r)   return nil;
    int mid = (l + r) >> 1;
    Complex *re = NewComplex(src[mid]);
    re->Combine(BuildTree(l,mid - 1),false);
    re->Combine(BuildTree(mid + 1,r),true);
    re->PushUp();
    return re;
}

Complex *Kth(Complex *a,int k)
{
	if(k <= a->son[0]->size)	return Kth(a->son[0],k);
	k -= a->son[0]->size;
	if(k == 1)	return a;
	return Kth(a->son[1],k - 1);
}

Complex *NewComplex(char val)
{
	Complex *re = new Complex();
	re->c = val;
	re->size = 1;
	re->son[0] = re->son[1] = nil;
	return re;
}

inline void Rotate(Complex *a,bool dir)
{
	Complex *f = a->father;
	f->son[!dir] = a->son[dir];
	f->son[!dir]->father = f;
	a->son[dir] = f;
	a->father = f->father;
	f->father->son[f->Check()] = a;
	f->father = a;
	f->PushUp();
	if(root == f)	root = a;
}

inline void Splay(Complex *a,Complex *aim)
{
	while(a->father != aim) {
		if(a->father->father == aim)
			Rotate(a,!a->Check());
		else if(!a->father->Check()) {
			if(!a->Check())
				Rotate(a->father,true),Rotate(a,true);
			else	Rotate(a,false),Rotate(a,true);
		}
		else {
			if(a->Check())
				Rotate(a->father,false),Rotate(a,false);
			else	Rotate(a,true),Rotate(a,false);
		}
	}
	a->PushUp();
}

void Print(Complex *a)
{
    if(a == nil)    return ;
    Print(a->son[0]);
    putchar(a->c);
    Print(a->son[1]);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值