bitset帮助离线合并实现O(n/w)
然后暴力就可以在n=100000时为所欲为
其实还是有点思想,
从大到小枚举height值,这样每次涉及到的问题的答案一定是height
另外离线会MLE?
那就分两次离呗。
没有什么是一次离线解决不了的,如果有,那就两次。
//从height大到小更新可以简化转移,因为height的最小值一定是你当前枚举的那一隅
#include<cstdio>
#include<cstring>
#include<cctype>
#include<bitset>
#include<algorithm>
#define maxn 100005
#define maxset 60005
using namespace std;
typedef bitset<maxset> Set;
int n,m;
char s[maxn],ss[maxn];
int cnt[maxn],sa[maxn],wa[maxn],wb[maxn],rk[maxn],h[maxn],ans[maxset];
bool sortcmp(const int &a,const int &b){
return h[a]>h[b];
}
bool cmp(int *r,const int &a,const int &b,int l){
if( r[a]==r[b] )
if(a+l<n && b+l<n)
return r[a+l]==r[b+l];
return 0;
}
void build(int n,int m){
int i,j,p,*x=wa,*y=wb,*t;
for(i=0;i<m;i++) cnt[i]=0;
for(i=0;i<n;i++) cnt[x[i]=s[i]]++;
for(i=1;i<m;i++) cnt[i]+=cnt[i-1];
for(i=n-1;i>=0;i--) sa[--cnt[x[i]]]=i;
for(p=0,j=1;p<n && j<n;j<<=1,m=p){
for(p=0,i=n-j;i<n;i++)
y[p++]=i;
for(i=0;i<n;i++)
if(sa[i]>=j)
y[p++]=sa[i]-j;
for(i=0;i<m;i++) cnt[i]=0;
for(i=0;i<n;i++) cnt[x[y[i]]]++;
for(i=1;i<m;i++) cnt[i]+=cnt[i-1];
for(i=n-1;i>=0;i--) sa[--cnt[x[y[i]]]]=y[i];
for(t=x,x=y,y=t,i=1,p=1,x[sa[0]]=0;i<n;i++)
x[sa[i]]=cmp(y,sa[i],sa[i-1],j)?p-1:p++;
}
}
int fa[maxn],seq[maxn];
int find(int now){
return fa[now]?fa[now]=find(fa[now]):now;
}
void calheight(int n){
int i,k=0;
for(i=0;i<n;i++) rk[sa[i]]=i;
for(i=0;i<n;h[rk[i++]]=k)
if(rk[i])
for(k?k--:0;s[i+k]==s[sa[rk[i]-1]+k];k++);
h[0]=0;
}
Set tak[maxn];
void solve(int Q){
int u,v;
for(int i=0;i<n;i++) tak[i]=Set();
for(int i=0;i<Q;i++){
scanf("%d%d",&u,&v);
u=n-u,v=n-v;
swap(u,v);
tak[rk[u]][i]=1;
if(v+1<n) tak[rk[v+1]][i]=1;
}
for(int i=1;i<n;i++) tak[rk[i]]^=tak[rk[i-1]];
memset(fa,0,sizeof fa);
Set ban;
for(int i=0;i<n-1;i++){
u=find(seq[i]),v=find(seq[i]-1);
Set now=(tak[u] & tak[v]) & (~ban);
for(int j=now._Find_next(-1);j<Q;j=now._Find_next(j)){
ban[j]=1;
ans[j]=h[seq[i]];
}
fa[u]=v;
tak[v]|=tak[u];
}
for(int i=0;i<Q;i++)
printf("%d\n",ans[i]);
}
int main(){
scanf("%d%d\n",&n,&m);
scanf("%s",ss);
for(int i=0;i<n;i++) s[i]=ss[n-i-1];
build(n,130);
calheight(n);
for(int i=0;i<n-1;i++) seq[i]=i+1;
sort(seq,seq+n-1,sortcmp);
solve((m>>1));
solve(m-(m>>1));
}