stl学习(三)crope的用法
来源:互联网 发布:淘宝请人代付退款 编辑:程序博客网 时间:2024/05/17 01:19
转载自http://blog.csdn.net/iamzky/article/details/38348653
曾经我不会写平衡树……于是在STL中乱翻……学到了pb_ds库中的SXBK的斐波那契堆、支持kth的set,和……ext/rope
先发一个官方的 说明 (鸣谢maoxiaohan1999):
http://www.sgi.com/tech/stl/Rope.html
再来例题
IOI2012
scrivener
题意
设计支持如下 3 种操作:
1.T x:在文章末尾打下一个小写字母 x。(type 操作)
2.U x:撤销最后的x 次修改操作。(Undo 操作)
(注意Query 操作并不算修改操作)
3.Q x:询问当前文章中第x 个字母并输出。(Query 操作)
操作数n<=100000 在线算法
clj都说这是道rope傻逼题……
我的rope标程:
#include<cstdio> #include<cstring> #include<cctype> #include<iostream> #include<algorithm> #include<ext/rope> using namespace std; using namespace __gnu_cxx; const int maxn=1e5+10; rope<char> *his[maxn]; int n; int d[maxn]; inline int lowbit(int x){ return x&-x; } inline void updata(int x){ while(x<=n){ d[x]++; x+=lowbit(x); } } inline int get(int x){ int res=0; while(x){ res+=d[x]; x-=lowbit(x); }return res; } inline char getC(){ char ch=getchar(); while(!isalpha(ch))ch=getchar(); return ch; } inline int getint(){ int res=0; char ch,ok=0; while(ch=getchar()){ if(isdigit(ch)){ res*=10;res+=ch-'0';ok=1; }else if(ok)break; }return res; } void deb(rope<char> s){ for(int i=0;i<s.length();i++) cout<<s[i];puts(""); } int main(){ freopen("type.in","r",stdin); freopen("type.out","w",stdout); n=getint(); his[0]=new rope<char>(); for(int i=1;i<=n;i++){ his[i]=new rope<char>(*his[i-1]); // deb(*his[i]); char opt=getC(); if(opt=='T'){ char x=getC(); his[i]->push_back(x); updata(i); }else if(opt=='U'){ updata(i); int x=getint(); int l=1,r=i,mid,now=get(i); while(l<r){ mid=(l+r)>>1; if(now-get(mid)>x) l=mid+1; else r=mid; } his[i]=his[l-1]; }else if(opt=='Q'){ int x=getint()-1; putchar(his[i]->at(x)); putchar('\n'); } // deb(*his[i]); } return 0; }可持久化在哪里呢?
his[i]=new rope<char>(*his[i-1]);
就是这一句!它可以实现O(1)的拷贝历史版本,由于rope的底层是平衡树,copy时copy根节点就行了
用它就可以轻松实现可持久化数组
其余操作不用多说
例二
AHOI2006文本编辑器editor
题意
设计数据结构支持
插入删除反转字符串
#include <cstdio> #include <ext/rope> #include <iostream> #include <algorithm> using namespace std; using namespace __gnu_cxx; crope a,b,tmp; char s[10]; int now,n,len,size; char str[2000000],rstr[2000000]; int main(){ scanf("%d",&n); while(n--){ scanf("%s",s); switch(s[0]){ case 'M':{scanf("%d",&now);break;} case 'P':{now--;break;} case 'N':{now++;break;} case 'G':{putchar(a[now]);putchar('\n');break;} case 'I':{ scanf("%d",&size); len=a.length(); for(int i=0;i<size;i++){ do{str[i]=getchar();} while(str[i]=='\n'); rstr[size-i-1]=str[i]; } rstr[size]=str[size]='\0'; a.insert(now,str); b.insert(len-now,rstr); break; } case 'D':{ scanf("%d",&size); len=a.length(); a.erase(now,size); b.erase(len-now-size,size); break; } case 'R':{ scanf("%d",&size); len=a.length(); tmp=a.substr(now,size); a=a.substr(0,now)+b.substr(len-now-size,size)+a.substr(now+size,len-now-size); b=b.substr(0,len-now-size)+tmp+b.substr(len-now,now); break; } } } return 0; }由于rope的底层实现,insert,erase,get都是logn的
就是翻转不行,不是自己手写的打不了标记啊!!
怎么办?
答:同时维护一正一反两个rope……反转即交换两个子串……Orz……
区间循环位移?简单,拆成多个子串连起来就好了……
区间a变b b变c c变d …… z变a? 呃……维护26个rope?
区间和?滚蛋,那是线段树的活
区间kth?sorry,与数值有关的操作rope一概不支持……
5555 维修数列只能自己写了……
最后的Hint:
rope的部分简单操作
函数功能push_back(x)在末尾添加xinsert(pos,x)在pos插入xerase(pos,x)从pos开始删除x个replace(pos,x)从pos开始换成xsubstr(pos,x)提取pos开始x个at(x)/[x]访问第x个元素友情提示:cena不支持rope
- stl学习(三)crope的用法
- STL学习(三)
- STL学习(三)
- STL学习笔记(三):STL的可扩展性
- STL的学习之( 三)
- STL学习之三:string用法示例
- C++学习三 STL的初级学习
- STL学习笔记(三) 堆的操作
- 关于c++中的STL的学习与再认识(三)
- C++学习 STL之三:deque用法详解
- STL学习(三)vector容器学习
- STL学习(三)deque容器学习
- STL学习之for_each的用法
- stl(list的用法)
- STL学习(三)仿函数
- 学习笔记(三)——STL
- STL学习之路三(vector)
- STL源码剖析学习笔记(三)
- Weiss-(DSAA - in C,2.13)求素数的3个方法
- 1082. Read Number in Chinese
- 数据结构之栈
- 第7周项目4 -列队数组
- 编译配置
- stl学习(三)crope的用法
- noip2013 转圈游戏 快速幂
- poj 3164 Command Network【最小树形图】
- 有1000桶酒,其中1桶有毒。而一旦吃了,毒性会在1周后发作。 现在我们用小老鼠做实验,要在1周内找出那桶毒酒,问最少需要多少老鼠。 (老鼠的使用量越少越好,注意,毒性1周后才会发作,而且一周后必须出
- css布局-搜索框制作
- python模块系列 (二)之操作NoSQL数据库hbase
- LINUX错误码
- android SQLite数据库1
- 命令行 TODO 工具中的王者