BZOJ1507 [NOI2003]Editor
AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=1507
【分析】
据说打完维修数列,什么数据结构题都是浮云了...这题似乎就是一个简化版咯。
这题的要求都和字母的值无关,而是与字母在序列中的位置有关...所以应当用位置关系建树的方法啦[就是每次找第k个位置就是这个节点的左边有k-1个节点]
首先预处理出两个虚拟节点作为开头和结尾[这个也是区间操作的比较基础的哦...]。
每次的添加就是找到光标和光标的下一个组成的区间,然后接在下一个的左子树上[联系之前的区间的做法...]
删除就是找到要删除的区间就好了...不过维修数列的心理阴影...我还是将节点回收了一下[会慢些...]。
输出的话也是找到区间然后输出中序遍历。
对于光标的操作直接设一个全局变量作为光标位置就好。
本题有一个坑点...就是“所有INSERT插入的字符数之和不超过2M(1M=1024*1024)”很可能一个INSERT就输进来2000000个字符哦....所以要开这么大。
[不过笔者偷偷瞄了数据只有1500000...]
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=1500010; struct Node{ int ch[2],f; int sz; char cc; }s[maxn]; int n,gb,rt; int tb[maxn],cot2,cot1; char ord[15],ch[maxn]; void update(int x){ s[x].sz=s[s[x].ch[0]].sz+s[s[x].ch[1]].sz+1; } void Rotate(int x,int k){ int y=s[x].f;s[x].f=s[y].f; if(s[y].f) s[s[y].f].ch[y==s[s[y].f].ch[1]]=x; s[y].ch[k]=s[x].ch[k^1]; if(s[x].ch[k^1]) s[s[x].ch[k^1]].f=y; s[y].f=x,s[x].ch[k^1]=y; update(y),update(x); } void Splay(int x,int gf){ int y; while(s[x].f!=gf){ y=s[x].f; if(s[y].f==gf) Rotate(x,x==s[y].ch[1]); else{int z=s[y].f; if(y==s[z].ch[0]){if(x==s[y].ch[0]) Rotate(y,0),Rotate(x,0);else Rotate(x,1),Rotate(x,0);} else {if(x==s[y].ch[1]) Rotate(y,1),Rotate(x,1);else Rotate(x,0),Rotate(x,1);} } } if(!gf) rt=x; } int Find(int k){ int p=rt; while(p){ if(k<=s[s[p].ch[0]].sz) p=s[p].ch[0]; else{ k-=s[s[p].ch[0]].sz; if(k==1) return p; k--;p=s[p].ch[1]; } } } int New_Node(){ int x; if(cot2) x=tb[cot2--]; else x=++cot1; s[x].sz=1; s[x].ch[0]=s[x].ch[1]=0; return x; } int build(int l,int r){ if(l>r) return 0; int mid=(l+r)>>1,x=New_Node(); s[x].ch[0]=build(l,mid-1); s[x].ch[1]=build(mid+1,r); s[x].cc=ch[mid]; if(s[x].ch[0]) s[s[x].ch[0]].f=x; if(s[x].ch[1]) s[s[x].ch[1]].f=x; update(x); return x; } void Del(int x){ if(!x) return;tb[++cot2]=x; Del(s[x].ch[0]),Del(s[x].ch[1]); } void Print(int x){ if(!x) return ; Print(s[x].ch[0]); if(s[x].cc) printf("%c",s[x].cc); Print(s[x].ch[1]); } int main(){ #ifndef ONLINE_JUDGE freopen("1507.in","r",stdin); freopen("1507.out","w",stdout); #endif int x,k,t,t1; gb=rt=New_Node(); s[rt].ch[1]=New_Node(); s[2].f=rt; update(rt); scanf("%d",&n); while(n--){ scanf("%s",ord); //Print(rt);putchar('\n'); if(strcmp(ord,"Move")==0) scanf("%d",&x),gb=x+1; else if(strcmp(ord,"Insert")==0){ scanf("%d",&x); for(int i=1;i<=x;i++){ scanf("%c",&ch[i]); if(ch[i]=='\n') i--; } k=build(1,x); t=Find(gb); Splay(t,0); if(s[rt].ch[1]){ t1=Find(gb+1);Splay(t1,rt); s[k].f=t1,s[t1].ch[0]=k; update(t1),update(rt); } else s[k].f=rt,s[rt].ch[1]=k,update(rt); } else if(strcmp(ord,"Delete")==0){ scanf("%d",&x); t=Find(gb);t1=Find(gb+x+1); Splay(t,0),Splay(t1,t); Del(s[t1].ch[0]); s[t1].ch[0]=0; update(t1),update(t); } else if(strcmp(ord,"Get")==0){ scanf("%d",&x); t=Find(gb),t1=Find(gb+x+1); Splay(t,0),Splay(t1,t); Print(s[t1].ch[0]); putchar('\n'); } else if(strcmp(ord,"Prev")==0) gb--; else gb++; } return 0; }