您的位置:首页 > 其它

BZOJ_1269_文本编辑器_[AHOI2006]_(Spaly)

2016-05-16 22:26 477 查看

描述

http://www.lydsy.com/JudgeOnline/problem.php?id=1269

BZOJ_1507很像的题,多了一个反转操作,还是Splay简单区间操作的模板题.

 

 

1269: [AHOI2006]文本编辑器editor

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 3223  Solved: 1203
[Submit][Status][Discuss]

 

Description

 

这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个简单而高效的文本编辑器。你能帮助他吗?为了明确任务目标,可可对“文本编辑器”做了一个抽象的定义:

#include <cstdio>
#include <algorithm>
using namespace std;

const int maxn=(1<<21)+5;

int n,at,cur,x;
char str[maxn],s[10];

struct Splay{
struct node{
node* ch[2],*pa;
char v; int s; bool rev;
node(char v,node* t):v(v){ ch[0]=ch[1]=pa=t; s=1; rev=false; }
bool d() { return pa->ch[1]==this; }
void setc(node* t,bool d) { ch[d]=t; t->pa=this; }
void push_up() { s=ch[0]->s+ch[1]->s+1; }
void push_down(){//向下传递反转
if(rev){
node* c0=ch[0],* c1=ch[1];
setc(c1,0); setc(c0,1);//调换左右子树的位置(貌似可以直接用swap,但刚开始还是自己写吧)
ch[0]->rev^=true; ch[1]->rev^=true;
rev=false;
}
}
}*root,*null;
Splay(){
null=new node('\0',NULL); null->s=0;
root=new node('?',null);
node* t=new node('!',null);
root->setc(t,1);
root->push_up();
}
void rot(node* o){
node* pa=o->pa; bool d=o->d();
pa->push_down(); o->push_down();//因为会改变o和pa,所以先把标记传递下去.
pa->pa->setc(o,pa->d());
pa->setc(o->ch[!d],d);
o->setc(pa,!d);
pa->push_up();
if(pa==root) root=o;
}
void splay(node* o,node* pa){
o->push_down();//如果需要转的话,在转的时候会向下传递,但如果不转的话,就在这里向下传递.
while(o->pa!=pa){
if(o->pa->pa==pa) rot(o);
else o->d()==o->pa->d()?(rot(o->pa),rot(o)):(rot(o),rot(o));
}
o->push_up();
}
node* kth(int k){
node* t=root; k++;
for(t->push_down();;t->push_down()){//每次顺便把标记传递下去.
int s=t->ch[0]->s+1;
if(s==k) return t;
if(k>s) k-=s,t=t->ch[1];
else t=t->ch[0];
}
}
node* find(int l,int r){
node* L=kth(l); splay(L,null);
node* R=kth(r); splay(R,L);
return R;
}
node* build(int l,int r){
if(l==r) return new node(str[l],null);
if(l>r) return null;
int m=l+(r-l)/2;
node* t=new node(str[m],null);
t->setc(build(l,m-1),0);
t->setc(build(m+1,r),1);
t->push_up();
return t;
}
void insert(int at,int cur){
node* t=find(at,at+1);
t->setc(build(0,cur),0); t->push_up();//因为在find函数中t是被splay过的,在splay中已经向下传递过标记了,所以这里不必再传递(remove函数中相同).
splay(t,null);
}
void remove(int at,int n){
node* t=find(at,at+n+1);
t->setc(null,0); t->push_up();
splay(t,null);
}
void setrev(int at,int n){//反转函数
node* t=find(at,at+n+1);
t->ch[0]->rev^=true;
t->push_down();
}
void print(node* o){
if(o==null) return;
o->push_down();//先向下传递,不然会错.
print(o->ch[0]);
printf("%c",o->v);
print(o->ch[1]);
}
void print(int at,int n){
node* t=find(at,at+n+1);
print(t->ch[0]);
printf("\n");
}
}tree;

int main(){
scanf("%d",&n);
while(n--){
scanf("%s",s);
if(s[0]=='I'){
scanf("%d",&x);
cur=0;
while(x--){
while(str[cur]=getchar(),str[cur]=='\n');
cur++;
}
cur--;
tree.insert(at,cur);
}
else if(s[0]=='M') scanf("%d",&at);
else if(s[0]=='D'){
scanf("%d",&x);
tree.remove(at,x);
}
else if(s[0]=='G') tree.print(at,1);
else if(s[0]=='R'){
scanf("%d",&x);
tree.setrev(at,x);
}
else if(s[0]=='P') at--;
else at++;
}
return 0;
}
View Code  

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: