Simple usage:
# Include <EXT/rope> using namespace _ gnu_cxx; int A [1000]; rope <int> X (A, A + n ); rope <int> A (x); X-> at (10); X [10]; X-> push_back (X) // Add XX-> insert (Pos, x) at the end. // insert XX-> erase (Pos, x) at the POS) // Delete X from pos-> Replace (Pos, x) // replace from POS with XX-> substr (Pos, x) // extract X from POS
Example 1:
Ioi2012
Scrivener
Question
The design supports the following three operations:
1. t x: enter a lowercase letter X at the end of the article. (Type Operation)
2. u x: undo the last X Modification Operation. (Undo operation)
(Note that the query operation is not a modification operation)
3. q X: Ask the X letter in the current article and output it. (Query Operation)
Operand n <= 100000 online Algorithm
CLJ says this is a silly question of 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;}
Among them, the operation to achieve persistence is: His [I] = new rope <char> (* his [I-1]);
It can implement the copy History version of O (1). Because rope's bottom layer is a red/black tree, you only need to copy the root pointer during copy.
One-click persistence ......
Example 2:
Bzoj 3673:Persistent and query set by zky
N sets, M operations
Operation:
1 a B Merge A and B in the Set
2 k returns to the status after the K operation (the query is counted as an operation)
3 a B: Check whether a and B belong to the same set. If yes, output 1. Otherwise, output 0.
0 <n, m <= 2*10 ^ 4
Analysis: You can directly persistently query the FA array of the set.
Accode:
#include <cstdio>#include <ext/rope>using namespace std;using namespace __gnu_cxx;const int maxm = 20010;rope<int> *rp[maxm];int find(int i,int x){ if(rp[i]->at(x) == x) return x; int f = find(i,rp[i]->at(x)); if(f == rp[i]->at(x)) return f; rp[i]->replace(x,f); return rp[i]->at(x);}inline void merge(int i,int x,int y){ x = find(i,x),y = find(i,y); if(x != y) rp[i]->replace(y,x);}int a[maxm],lastans;int main(){ int n,m; scanf("%d%d",&n,&m); for(int i = 1;i <= n;i ++) a[i] = i; rp[0] = new rope<int> (a,a + n + 1); for(int i = 1;i <= m;i ++) { rp[i] = new rope<int> (*rp[i - 1]); int opt; scanf("%d",&opt); if(opt == 1) { int a,b; scanf("%d%d",&a,&b); merge(i,a/* ^ lastans*/,b/* ^ lastans*/); } else if(opt == 2) { int k; scanf("%d",&k); rp[i] = rp[k/* ^ lastans*/]; } else { int a,b; scanf("%d%d",&a,&b); printf("%d\n",lastans = (find(i,a/* ^ lastans*/) == find(i,b/* ^ lastans*/))); } } return 0;}
Example 3:
Ahoi2006 text editor Editor
Question
Design Data Structure support
Insert and delete reverse string
Analysis:
Because of the underlying implementation of rope, insert, erase, and get are all logn
You can't flip it. You can't mark it manually !!
What should I do?
A: At the same time, we maintain one, one, and two ropes ...... Invert: swap two substrings ...... Orz ......
Interval Cyclic Displacement? Simple. Just split them into multiple sub-databases and concatenate them ......
Range A to B to C to D ...... Z changed to? Er ...... Maintain 26 ropes?
Interval and? It's a live line tree.
Interval kth? Sorry, numeric-related operations rope does not support ......
5555 the maintenance series can only be written by yourself ......
Accode:
#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; }
End