1. 程式人生 > >[學習筆記]後綴平衡樹

[學習筆記]後綴平衡樹

例題 putchar query view printf \n eve 字典序 線段樹

後綴數組+平衡樹=後綴平衡樹

支持動態插入字符(只能往前插入),即插入一個後綴,維護所有後綴的排名

插入後綴找到位置?平衡樹上二分

法一:

哈希+二分,太慢

法二:

第一個字符不同,已經可以比較,否則比較第二個字符開始的後綴,之前這兩個後綴排名已經處理好了。直接比較排名即可。

查詢任意位置的排名?

法一:

暴力這個點往上跳log次,找到rank

法二:

每個點打一個tag,把排名“絕對化”

記錄[l,r],val,表示x子樹的tag值域區間和x的值val,val=(l+r)/2

這樣可以O(1)查排名

總值域是[1,inf],深度logn,所以開個double一定精度沒有問題。

具體用重量平衡樹維護(子樹大小期望logn,如treap或者SGT),SGT就可以啦

這樣直接重構的時候把[l,r]tag重新賦值。(treap旋轉時候必須直接重構。否則tag就亂了)

例題

bzoj3682: Phorni

線段樹維護區間字典序最小的id即可

註意:

由於tag或者排名是不斷變化的,不能記錄tag的值,只要記錄id是哪一個即可。

因為新插入後綴,相對排名不影響

改變某一個pos[x]只會影響到根的結果。

pushup時候現場比較

技術分享圖片
#include<bits/stdc++.h>
#define reg register int
#define
il inline #define fi first #define se second #define mk(a,b) make_pair(a,b) #define numb (ch^‘0‘) #define pb push_back #define solid const auto & #define enter cout<<endl #define pii pair<int,int> using namespace std; typedef long long ll; template<class T>il void rd(T &x){
char ch;x=0;bool fl=false; while(!isdigit(ch=getchar()))(ch==-)&&(fl=true); for(x=numb;isdigit(ch=getchar());x=x*10+numb); (fl==true)&&(x=-x); } template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+0);} template<class T>il void ot(T x){if(x<0) putchar(-),x=-x;output(x);putchar( );} template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar(\n);} namespace Miracle{ const int N=500000+5; const int M=1000000+5; const double inf=1e18; const double alp=0.75; #define mid ((l+r)>>1) #define Md ((L+R)/2.0) int n,q,m,typ; int pos[N]; char s[M]; int rt; namespace SGT{ struct node{ int ch[2]; int sz; double l,r; double val; void init(double L,double R){ sz=1;ch[0]=ch[1]=0;l=L;r=R;val=(L+R)/2; } }t[M]; int tot; #define ls t[x].ch[0] #define rs t[x].ch[1] void pushup(int x){ if(!x) return; t[x].sz=t[ls].sz+t[rs].sz+1; } bool isbad(int x){ return (t[ls].sz>t[x].sz*alp||t[rs].sz>t[x].sz*alp); } int q[M],num; void dfs(int x){ if(!x) return; dfs(ls); q[++num]=x; dfs(rs); } int build(int l,int r,double L,double R){ if(l>r) return 0; int x=q[mid]; t[x].init(L,R); ls=build(l,mid-1,L,Md); rs=build(mid+1,r,Md,R); pushup(x); return x; } void rebuild(int &x){ num=0;dfs(x); x=build(1,num,t[x].l,t[x].r); } int sta[M],top; void che(){ for(reg i=1;i<=top;++i){ if(isbad(sta[i])){ if(i==1) rebuild(rt); else rebuild(t[sta[i-1]].ch[t[sta[i-1]].ch[1]==sta[i]]),pushup(sta[i-1]); return; } } } bool cmp(int x,int y){//x<y? if(s[x]!=s[y]) return s[x]<s[y]; return t[x-1].val<t[y-1].val; } void ins(int p){//x is pos ++tot; if(!rt){ rt=tot; t[tot].init(1,inf); return; } int x=rt; top=0; while(1){ int d=cmp(x,p); sta[++top]=x; ++t[x].sz; if(!t[x].ch[d]){ t[x].ch[d]=tot; if(d==1){//rson t[tot].init(t[x].val,t[x].r); }else{ t[tot].init(t[x].l,t[x].val); } break; } x=t[x].ch[d]; } che(); } void pb(int x){ ins(x); } #undef ls #undef rs } namespace SMT{ #define ls (x<<1) #define rs (x<<1|1) struct node{ int id; }t[4*N]; int chm(int x,int y){ return SGT::t[pos[x]].val<=SGT::t[pos[y]].val?x:y; } void pushup(int x){ t[x].id=chm(t[ls].id,t[rs].id); } void build(int x,int l,int r){ if(l==r){ t[x].id=l;return; } build(ls,l,mid); build(rs,mid+1,r); pushup(x); } void upda(int x,int l,int r,int p){ if(l==r){ t[x].id=l;return; } if(p<=mid) upda(ls,l,mid,p); else upda(rs,mid+1,r,p); pushup(x); } int query(int x,int l,int r,int L,int R){ if(L<=l&&r<=R){ return t[x].id; } if(L>mid) return query(rs,mid+1,r,L,R); if(R<=mid) return query(ls,l,mid,L,R); return chm(query(ls,l,mid,L,R),query(rs,mid+1,r,L,R)); } } int main(){ rd(n);rd(q);rd(m);rd(typ); scanf("%s",s+1); reverse(s+1,s+m+1); for(reg i=1;i<=n;++i){ rd(pos[i]); } for(reg i=1;i<=m;++i){ SGT::pb(i); } SMT::build(1,1,n); char ch[233]; int x,y; int lasans=0; while(q--){ scanf("%s",ch); if(ch[0]==I){ rd(x); if(typ) x=x^lasans; s[++m]=a+x; SGT::pb(m); }else if(ch[0]==C){ rd(x);rd(y); pos[x]=y; SMT::upda(1,1,n,x); }else if(ch[0]==Q){//warning!!! rd(x);rd(y); int now=SMT::query(1,1,n,x,y); lasans=now; printf("%d\n",lasans); //update lasans } } return 0; } } signed main(){ Miracle::main(); return 0; } /* Author: *Miracle* */
View Code

[學習筆記]後綴平衡樹