洛谷传送门
BZOJ传送门
题解:
求LCP显然直接哈希二分就行了,由于需要支持中间插入一个字符,需要用平衡树。
由于这道题没有区间合并操作,而且好像有点卡FHQ_Treap和Splay,本着科学打脸观写了一发替罪羊跑到飞起。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define gc get_char
#define cs const
namespace IO{
inline char get_char(){
static cs int Rlen=1<<22|1;
static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
inline char getalpha(){char c;while(!isalpha(c=gc()));return c;}
template<typename T>
inline T get(){
char c;
while(!isdigit(c=gc()));T num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}
inline int getint(){return get<int>();}
}
using namespace IO;
using std::cerr;
using std::cout;
#define ull unsigned ll
cs int N=1e5+5;
cs ull b=47;
ull pw[N];
inline void Hash_init(){
pw[0]=1;
for(int re i=1;i<N;++i)pw[i]=pw[i-1]*b;
}
char s[N];
namespace SGT{
int val[N];
ull sum[N];
int lc[N],rc[N];
int siz[N],now;
int nd[N],cnt;
cs double alpha=0.6;
int rt,*p;
inline void pushup(int u){
sum[u]=sum[lc[u]]*pw[siz[rc[u]]+1]+val[u]*pw[siz[rc[u]]]+sum[rc[u]];
siz[u]=siz[lc[u]]+1+siz[rc[u]];
}
inline bool bad(int u){
return siz[lc[u]]>siz[u]*alpha||siz[rc[u]]>siz[u]*alpha;
}
void dfs_get(int u){
if(!u)return ;
dfs_get(lc[u]);
nd[++cnt]=u;
dfs_get(rc[u]);
}
inline void build(int &u,int l,int r){
int mid=l+r>>1;
u=nd[mid];lc[u]=rc[u]=0;
if(l<mid)build(lc[u],l,mid-1);
if(mid<r)build(rc[u],mid+1,r);
pushup(u);
}
inline void insert(int &u,int k,int v){
if(!u){
u=++now;
val[u]=sum[u]=v;
siz[u]=1;
return ;
}
if(k<=siz[lc[u]])insert(lc[u],k,v);
else insert(rc[u],k-siz[lc[u]]-1,v);
pushup(u);
if(bad(u))p=&u;
}
inline void modify(int u,int k,int v){
if(k<=siz[lc[u]])modify(lc[u],k,v);
else if(k==siz[lc[u]]+1)val[u]=v;
else modify(rc[u],k-siz[lc[u]]-1,v);
pushup(u);
}
inline ull query(int u,int l,int r){
if(l==1&&r==siz[u])return sum[u];
if(l>r)return 0;
if(r<=siz[lc[u]])return query(lc[u],l,r);
if(siz[lc[u]]+1<l)return query(rc[u],l-siz[lc[u]]-1,r-siz[lc[u]]-1);
return query(lc[u],l,siz[lc[u]])*pw[r-siz[lc[u]]]+val[u]*pw[r-siz[lc[u]]-1]+query(rc[u],1,r-siz[lc[u]]-1);
}
inline void init(){
scanf("%s",s+1);now=strlen(s+1);
cnt=now;
for(int re i=1;i<=cnt;++i)nd[i]=i,val[i]=s[i]-'a';
build(rt,1,cnt);
}
inline void final_string(){
cnt=0;
dfs_get(rt);
for(int re i=1;i<=cnt;++i)cout<<(char)(val[nd[i]]+'a');
}
}
inline void Insert(int pos,int v){
using namespace SGT;
p=NULL;
insert(rt,pos,v);
if(p!=NULL){
cnt=0;
dfs_get(*p);
build(*p,1,cnt);
}
}
inline void Modify(int pos,int v){SGT::modify(SGT::rt,pos,v);}
inline ull Query(int l,int r){return SGT::query(SGT::rt,l,r);}
inline int query(int x,int y){
int l=0,r=SGT::now-std::max(x,y)+1;
while(l<r){
int mid=(l+r+1)>>1;
if(Query(x,x+mid-1)==Query(y,y+mid-1))l=mid;
else r=mid-1;
}
return l;
}
signed main(){
Hash_init();
SGT::init();
int T=getint();
while(T--)switch(getalpha()){
case 'Q':cout<<query(getint(),getint())<<"\n";break;
case 'R':{
int x=getint();
Modify(x,getalpha()-'a');
break;
}
case 'I':{
int x=getint();
Insert(x,getalpha()-'a');
break;
}
}
return 0;
}