[NOI2003]文本编辑器
题目:洛谷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; }