zoukankan      html  css  js  c++  java
  • BZOJ3682 Phorni 后缀平衡树

    后缀平衡树的裸题

    后缀平衡树简单的思想如下 具体的可以去看(clj)的论文

    假设我们已经有了串(S)的后缀平衡树
    插入一个字母(c)
    我们用(Si)代表原串(S)从第(i)个字符开始的后缀
    则后缀(cS)与任意一个后缀(Si)的大小关系可以用
    (c)(Si)的第一个字母的大小关系
    以及 后缀(S1)与后缀(Si+1)的大小关系来表示
    前面是两个字符的比较(O(1))
    后面两个原串后缀的大小关系由后缀平衡树所代表其的节点标号快速得出两个后缀大小 (O(1))

    于是我们只要维护一个平衡树来(O(1))求出任意后缀的(rank) 再建一个线段树来区间查询,单点修改就可以了

    #include<bits/stdc++.h>
    using namespace std;
    #define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
    #define pa pair<int,int>
    #define mod 1000000007
    #define ll long long
    #define mk make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define lb double
    #define cl(x) memset(x,0,sizeof x)
    #ifdef Devil_Gary
    #define bug(x) cout<<(#x)<<" "<<(x)<<endl
    #define debug(...) fprintf(stderr, __VA_ARGS__)
    #else
    #define bug(x)
    #define debug(...)
    #endif
    const int INF = 0x7fffffff;
    const int N=1e6+5;
    const lb alpha=0.85;
    /*
    char *TT,*mo,but[(1<<15)+2];
    #define getchar() ((TT==mo&&(mo=(TT=but)+fread(but,1,1<<15,stdin),TT==mo))?-1:*TT++)//*/
    inline int read(){
        int x=0,rev=0,ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')rev=1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return rev?-x:x;
    }
    char s[N],ss[5];
    int n,m,len,typ,lstans,sit[N],at[N];
    lb v[N];
    struct SuffixBT{
    	int ls[N],rs[N],sz[N],sf[N],rt,cnt;
    	int tmp[N],cc;
    	int fail,fafail;
    	lb fl,fr;
    	bool cmp(int x,int y){
    		if(!x||!y) return !x;
    		if(s[x]!=s[y]) return s[x]<s[y];
    		return v[at[x-1]]<v[at[y-1]];
    	}
    	void update(int pos,lb l,lb r){
    		sz[pos]=sz[ls[pos]]+sz[rs[pos]]+1;
    		if(max(sz[ls[pos]],sz[rs[pos]])>sz[pos]*alpha) fail=pos,fafail=-1,fl=l,fr=r;
    		else if(fail==ls[pos]||fail==rs[pos]) fafail=pos;
    	}
    	void insert(int&pos,lb l,lb r,int&id){
    		if(!pos){
    			v[at[id]=pos=++cnt]=(l+r)/2.0,sz[pos]=1,sf[pos]=id;
    			return;
    		}
    		lb vmid=(l+r)/2.0;
    		cmp(sf[pos],id)?insert(rs[pos],vmid,r,id):insert(ls[pos],l,vmid,id);
    		update(pos,l,r);;
    	}
    	int rebuild(int nl,int nr,lb l,lb r){
    		int mid=nl+nr>>1,pos=tmp[mid];
    		lb vmid=(l+r)/2.0;
    		v[pos]=vmid,sz[pos]=nr-nl+1;
    		if(nl<mid) ls[pos]=rebuild(nl,mid-1,l,vmid);
    		if(nr>mid) rs[pos]=rebuild(mid+1,nr,vmid,r);
    		return pos;
    	}
    	void dfs(int pos){
    		if(ls[pos]) dfs(ls[pos]);
    		tmp[++cc]=pos;
    		if(rs[pos]) dfs(rs[pos]);
    		ls[pos]=rs[pos]=sz[pos]=0;
    	}
    	void insert(int &id){
    		fail=0,fafail=-1,insert(rt,0,1,id);
    		if(fail){
    			cc=0,dfs(fail);
    			if(fafail!=-1) (fail==ls[fafail])? ls[fafail]=rebuild(1,cc,fl,fr):rs[fafail]=rebuild(1,cc,fl,fr);
    			else rt=rebuild(1,cc,0,1);
    		}
    	}
    }sbt;
    struct SGT{
    	int t[N<<2];
    	bool cmp(int a,int b){
    		if(sit[a]==sit[b]) return a<b;
    		return v[at[sit[a]]]<v[at[sit[b]]];
    	}
    	void update(int pos){
    		t[pos]=cmp(t[pos<<1],t[pos<<1|1])?t[pos<<1]:t[pos<<1|1];
    	}
    	void build(int pos,int l,int r){
    		if(l==r){
    			t[pos]=l;
    			return;
    		}
    		int mid=l+r>>1;
    		build(pos<<1,l,mid),build(pos<<1|1,mid+1,r),update(pos);
    	}
    	void modify(int pos,int l,int r,int x){
    		if(l==r) return;
    		int mid=l+r>>1;
    		if(x<=mid) modify(pos<<1,l,mid,x);
    		else modify(pos<<1|1,mid+1,r,x);
    		update(pos);
    	}
    	int Query(int pos,int l,int r,int nl,int nr){
    		if(nl<=l&&r<=nr) return t[pos];
    		int mid=l+r>>1;
    		if(nr<=mid) return Query(pos<<1,l,mid,nl,nr);
    		else if(nl>mid) return Query(pos<<1|1,mid+1,r,nl,nr);
    		int ql=Query(pos<<1,l,mid,nl,nr),qr=Query(pos<<1|1,mid+1,r,nl,nr);
    		return cmp(ql,qr)?ql:qr;
    	}
    }sgt;
    int main(){
    #ifdef Devil_Gary
    	freopen("in.txt","r",stdin);
    #endif
    	n=read(),m=read(),len=read(),typ=read(),scanf("%s",s+1),reverse(s+1,s+len+1);
    	for(int i=0;i<=len;i++) s[i]-='a',sbt.insert(i);
    	for(int i=1;i<=n;i++) sit[i]=read();
    	sgt.build(1,1,n);
    	for(int i=1,c,x,l,r;i<=m;i++){
    		scanf("%s",ss);
    		if(ss[0]=='I'){
    			c=read();
    			if(typ) c^=lstans;
    			s[++len]=c,sbt.insert(len);
    		}
    		else if(ss[0]=='C') x=read(),sit[x]=read(),sgt.modify(1,1,n,x);
    		else if(ss[0]=='Q') l=read(),r=read(),printf("%d
    ",lstans=sgt.Query(1,1,n,l,r));
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    关于CSS自文档的思考_css声明式语言式代码注释
    html5中contenteditable属性如果过滤标签,过滤富文本样式
    web前端工程化/构建自动化
    Python连载19-装饰器
    Java连载1-概述&常用的dos命令
    HTML连载18-id选择器与class区别&class选择器使用思路&后代选择器
    Python连载18-closure闭包解释及其注意点
    HTML连载17-id选择器&类选择器
    Python连载17-排序函数&返回函数的函数
    HTML连载16-颜色控制属性2&标签选择器
  • 原文地址:https://www.cnblogs.com/devil-gary/p/9202128.html
Copyright © 2011-2022 走看看