后缀平衡树裸题。
后缀平衡树呢,实际上是一个很naive的东西。就是用平衡树维护后缀数组。
这样的话就可以支持在最前端插入一个字符(相当于插入新的后缀)
每次比较节点的tag是O(1)的,所以可以快速的支持插入和查询。
为了保证重构的复杂度,后缀平衡树必须使用重量平衡树。
如替罪羊树,Treap,Weight-Balanced-Finger-Tree等。
#include<bits/stdc++.h> #define N 1000005 #define lson (o<<1) #define rson (o<<1|1) using namespace std; typedef long long ll; int c[N][2],rnd[N],val[N],cnt;ll key[N]; int t[N<<2],pos[N],n,m,type,len,LastOrder=0,rt; char s[N]; inline bool cmp(int x,int y){return (val[x]<val[y]||(val[x]==val[y]&&key[x-1]<key[y-1]));} void rebuild(int &x,ll l,ll r){ if(!x)return ;ll mid=(l+r)>>1; key[x]=mid; rebuild(c[x][0],l,mid-1); rebuild(c[x][1],mid+1,r); } inline void rotate(int x,int &y,ll l,ll r){ int p=c[y][1]==x;c[y][p]=c[x][p^1]; c[x][p^1]=y;y=x; rebuild(y,l,r); } void ins(int &x,int p,ll l,ll r){ if(!x){key[x=cnt]=(l+r)>>1;return;} ll mid=(l+r)>>1; if(cmp(p,x)){ ins(c[x][0],p,l,mid-1); if(rnd[c[x][0]]>rnd[x])rotate(c[x][0],x,l,r); } else{ ins(c[x][1],p,mid+1,r); if(rnd[c[x][1]]>rnd[x])rotate(c[x][1],x,l,r); } } inline int get(int x,int y){return key[pos[x]]<=key[pos[y]]?x:y;} inline void pushup(int o){t[o]=get(t[lson],t[rson]);} void build(int o,int l,int r){ if(l==r){t[o]=l;return;} int mid=(l+r)>>1; build(lson,l,mid);build(rson,mid+1,r); pushup(o); } void change(int o,int l,int r,int q,int v){ if(l==r){pos[q]=v;return;} int mid=(l+r)>>1; if(q<=mid)change(lson,l,mid,q,v); else change(rson,mid+1,r,q,v); pushup(o); } int query(int o,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr)return t[o]; int mid=(l+r)>>1; if(qr<=mid)return query(lson,l,mid,ql,qr); else if(ql>mid)return query(rson,mid+1,r,ql,qr); else return get(query(lson,l,mid,ql,qr),query(rson,mid+1,r,ql,qr)); } inline int read(){ int f=1,x=0;char ch; do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9'); do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9'); return f*x; } int main(){ n=read();m=read();len=read();type=read(); scanf("%s",s+1); for(int i=1;i<=len;i++){ val[++cnt]=s[len-i+1]-'a'+1; rnd[cnt]=rand(); ins(rt,i,1,1LL<<61); } for(int i=1;i<=n;i++)pos[i]=read(); build(1,1,n); while(m--){ scanf("%s",s); if(s[0]=='I'){ int x=read();if(type)x^=LastOrder; val[++cnt]=++x;rnd[cnt]=rand(); ins(rt,cnt,1,1LL<<61); } if(s[0]=='C'){int x=read(),y=read();change(1,1,n,x,y);} if(s[0]=='Q'){ int x=read(),y=read();LastOrder; printf("%d ",LastOrder=query(1,1,n,x,y)); } } }