题目:洛谷P4008、BZOJ1507。
题目大意:
一堆操作。
1. 光标移动到指定位置
2. 在光标后插入一串字符
3. 在光标后删除一串字符
4. 光标前移
5. 光标后移
6. 输出光标后的一串字符
解题思路:
非旋Treap即可,插入时一个一个字符插也没什么问题,开O2就可以过(BZOJ过不去)。
C++ Code:
#include<bits/stdc++.h>
int t,rt=0,cnt=0,n,gb;
struct node{
int r,ls,rs,sz;
char s;
}a[5000005];
char opt;
inline void update(int x){a[x].sz=a[a[x].ls].sz+a[a[x].rs].sz+1;}
int merge(int x,int y){
if(!x||!y)return x+y;
if(a[x].r<a[y].r){
a[x].rs=merge(a[x].rs,y);
update(x);
return x;
}else{
a[y].ls=merge(x,a[y].ls);
update(y);
return y;
}
}
void split(int u,int k,int& x,int& y){
if(k==0){x=0,y=u;return;}
if(a[u].sz==k){x=u,y=0;return;}
if(a[a[u].ls].sz>=k)split(a[u].ls,k,x,a[u].ls),y=u;else
split(a[u].rs,k-a[a[u].ls].sz-1,a[u].rs,y),x=u;
update(u);
}
void print(int now){
if(!now)return;
print(a[now].ls);
putchar(a[now].s);
print(a[now].rs);
}
inline int readint(){
int c=getchar(),d=0;
for(;!isdigit(c);c=getchar());
for(;isdigit(c);c=getchar())
d=(d<<3)+(d<<1)+(c^'0');
return d;
}
int main(){
srand(20170607);
memset(a,0,sizeof a);
gb=0;
for(t=readint();t--;){
opt=getchar();
for(;!isalpha(opt);opt=getchar());
if(opt=='I'){
n=readint();
int oldgb=gb;
while(n--){
char c=getchar();
while(c<32||c>126)c=getchar();
a[++cnt]=(node){rand(),0,0,1,c};
int x,y;
split(rt,gb++,x,y);
rt=merge(merge(x,cnt),y);
}
gb=oldgb;
}else
if(opt=='D'){
n=readint();
int x,y,z;
split(rt,gb,x,y);
split(y,n,y,z);
rt=merge(x,z);
}else
if(opt=='M')gb=readint();else
if(opt=='P')--gb,getchar(),getchar(),getchar();else
if(opt=='N')++gb,getchar(),getchar(),getchar();else{
n=readint();
int x,y,z;
split(rt,gb,x,y);
split(y,n,y,z);
print(y);putchar('\n');
rt=merge(merge(x,y),z);
}
//print(rt);
}
return 0;
}
以下为笛卡尔树建树版本,跑的快了不止一点点,能在BZOJ上过了。
C++ Code:
#include<bits/stdc++.h>
int t,rt=0,cnt=0,n,gb,top=0,sta[5000005];
struct node{
int r,ls,rs,sz;
char s;
}a[5000005];
char opt,s[5000005];
inline void update(int x){a[x].sz=a[a[x].ls].sz+a[a[x].rs].sz+1;}
int merge(int x,int y){
if(!x||!y)return x+y;
if(a[x].r<a[y].r){
a[x].rs=merge(a[x].rs,y);
update(x);
return x;
}else{
a[y].ls=merge(x,a[y].ls);
update(y);
return y;
}
}
void split(int u,int k,int& x,int& y){
if(k==0){x=0,y=u;return;}
if(a[u].sz==k){x=u,y=0;return;}
if(a[a[u].ls].sz>=k)split(a[u].ls,k,x,a[u].ls),y=u;else
split(a[u].rs,k-a[a[u].ls].sz-1,a[u].rs,y),x=u;
update(u);
}
void print(int now){
if(!now)return;
print(a[now].ls);
putchar(a[now].s);
print(a[now].rs);
}
inline int readint(){
int c=getchar(),d=0;
for(;!isdigit(c);c=getchar());
for(;isdigit(c);c=getchar())
d=(d<<3)+(d<<1)+(c^'0');
return d;
}
int build(int n){
int x,pre;
for(int i=1;i<=n;++i){
a[x=++cnt]=(node){rand(),0,0,1,s[i]};
for(pre=0;top&&a[sta[top]].r>a[x].r;--top)update(pre=sta[top]);
if(top)a[sta[top]].rs=x;
a[sta[++top]=x].ls=pre;
}
while(top)update(sta[top--]);
return sta[1];
}
int main(){
srand(20170607);
memset(a,0,sizeof a);
gb=0;
for(t=readint();t--;){
opt=getchar();
for(;!isalpha(opt);opt=getchar());
if(opt=='I'){
n=readint();
for(int i=1;i<=n;++i){
char c=getchar();
while(c<32||c>126)c=getchar();
s[i]=c;
}
int x=build(n),y,z;
split(rt,gb,y,z);
rt=merge(merge(y,x),z);
}else
if(opt=='D'){
n=readint();
int x,y,z;
split(rt,gb,x,y);
split(y,n,y,z);
rt=merge(x,z);
}else
if(opt=='M')gb=readint();else
if(opt=='P')--gb,getchar(),getchar(),getchar();else
if(opt=='N')++gb,getchar(),getchar(),getchar();else{
n=readint();
int x,y,z;
split(rt,gb,x,y);
split(y,n,y,z);
print(y);putchar('\n');
rt=merge(merge(x,y),z);
}
//print(rt);
}
return 0;
}