CF741E Arpa’s abnormal DNA and Mehrdad’s deep interest
题意:给定两个串\(S\)和\(T\),定义\(R_i\)为在\(s_i\)和\(s_{i+1}\)之间插入\(T\)串得到的字符串。\(i \in [0,|S|]\)
有\(Q\)次询问,形如\((l,r,k,x,y)\),求满足 \(l \leq i \leq r\) 且 \(x\) \(\leq\) \(i\) mod \(k\) \(\leq y\) 的所有\(i\)中,字典序最小的\(i\)。
\(|S|,|T|,Q \leq 10^5\)
题解:首先需要解决排序问题。我们可以对\(S + T\)建立后缀数组,求lcp。然后把1到n排个序。
比较\(i\)和\(j\)时,分两个串的\(T\)串部分是否相交讨论,相当于将两个串划成了五段,分别比较大小即可。
然后考虑这个奇怪的对\(i\)的限制。
发现所有合法的\(i\)都可以写成\(a+pk\)的形式,这样,所有合法的\(i\)可以看做是\(a\)轴,\(p\)轴的平面直角坐标系下的一个矩形。
由于矩形面积是\(O(n)\)的,而其边长的较小值不会超过\(\sqrt{n}\),所以我们只要能快速求出一行或一列的解,就能在\(O(\sqrt{n})\)的时间内解决单个问题了。
因此,我们进行根号分治。
对于较大的\(k\),我们枚举\(p\),对于连续的一段\([x+pk,y+pk]\),可以用st表预处理做到\(O(1)\)查询。
对于较小的\(k\),我们将所有询问离线下来,对于每个\(k\),每个\(a\),我们都建立一个st表,进行快速查询。由于\(k,a\)是\(\sqrt n\)级别的,所以st表最多处理\(n \sqrt n\)个元素,时间复杂度是\(O(n \sqrt n logn)\)。
代码:
#include<bits/stdc++.h>
using namespace std;
#define re register int
#define F(x,y,z) for(re x=y;x<=z;x++)
#define FOR(x,y,z) for(re x=y;x>=z;x--)
typedef long long ll;
#define I inline void
#define IN inline int
#define C(x,y) memset(x,y,sizeof(x))
#define STS system("pause")
template<class D>I read(D &res){
res=0;register D g=1;register char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')g=-1;
ch=getchar();
}
while(isdigit(ch)){
res=(res<<3)+(res<<1)+(ch^48);
ch=getchar();
}
res*=g;
}
const int N=316,Mx=200000;
char s[101000],t[101000];
int a[101000],b[101000],c[202000];
struct P{
int l,r,k,x,y,id;
friend bool operator < (P a,P b){return a.k<b.k;}
}p[101000];
int n,m,q,len,L,R,ans[101000],sa[202000],rk[202000],tp[202000],tot,buc[202000],hei[202000],num,f[202000][20],lg[202000],h[202000][20];
int xu[101000],rak[101000],g[202000][20];
IN ques_lcp(int x,int y){
// cout<<"L"<<x<<" "<<y<<endl;
if(x==y)return len-x+1;
x=rk[x];y=rk[y];if(x>y)swap(x,y);x++;
re ln=lg[y-x+1];
return min(f[x][ln],f[y-(1<<ln)+1][ln]);
}
inline bool bbb(int x,int y){
re res=0,cp;
if(x>y)swap(x,y),res=1;
if(x+m>y){
cp=ques_lcp(n+1,x+1);
// cout<<"!"<<cp<<endl;
if(cp<y-x)return (b[cp+1]<a[x+1+cp])^res;
cp=ques_lcp(n+y-x+1,n+1);
// cout<<"@"<<cp<<endl;
if(cp<x+m-y)return (b[y-x+cp+1]<b[cp+1])^res;
cp=ques_lcp(x+1,n+x+m-y+1);
// cout<<"#"<<cp<<endl;
if(cp<y-x)return (a[x+cp+1]<b[x+m-y+cp+1])^res;
return res^1;
}
else{
cp=ques_lcp(n+1,x+1);
if(cp<m)return (b[cp+1]<a[x+1+cp])^res;
cp=ques_lcp(x+1,x+m+1);
if(cp<y-x-m)return (a[x+cp+1]<a[x+m+cp+1])^res;
cp=ques_lcp(y-m+1,n+1);
if(cp<m)return (a[y-m+cp+1]<b[cp+1])^res;
return res^1;
}
}
IN ckmin(int x,int y){if(x==-1||y==-1)return x+y+1;if(x==y)return x;return rak[x]<rak[y]?x:y;}
IN ques(int x,int y){
re ln=lg[y-x+1];return ckmin(g[x][ln],g[y-(1<<ln)+1][ln]);
}
IN ques_min(int x,int y){
if(x>y)return -1;
// cout<<"@"<<x<<" "<<y<<endl;
re ln=lg[y-x+1];return ckmin(h[x][ln],h[y-(1<<ln)+1][ln]);
}
I build_sa(){
F(i,1,n)a[i]=s[i]-'a'+1;F(i,1,m)b[i]=t[i]-'a'+1;
F(i,1,n)c[i]=a[i];F(i,1,m)c[n+i]=b[i];len=n+m;
num=30;
F(i,1,len)buc[rk[i]=c[i]]++;
F(i,1,num)buc[i]+=buc[i-1];
FOR(i,len,1)sa[buc[rk[i]]--]=i;
for(re k=1;k<=len;k<<=1){
tot=0;
F(i,len-k+1,len)tp[++tot]=i;
F(i,1,len)if(sa[i]>k)tp[++tot]=sa[i]-k;
F(i,1,num)buc[i]=0;
F(i,1,len)buc[rk[i]]++;
F(i,1,num)buc[i]+=buc[i-1];
FOR(i,len,1)sa[buc[rk[tp[i]]]--]=tp[i],tp[i]=0;
swap(rk,tp);rk[sa[1]]=tot=1;
F(i,2,len)rk[sa[i]]=(tp[sa[i-1]]==tp[sa[i]]&&tp[sa[i-1]+k]==tp[sa[i]+k])?tot:++tot;
if(tot==len)break;
num=tot;
}
re k=0;
F(i,1,len){
if(rk[i]==1)continue;
if(k)k--;
re p=sa[rk[i]-1];
while(c[i+k]==c[p+k])k++;
hei[rk[i]]=k;
}
F(i,1,len)f[i][0]=hei[i];
F(j,1,lg[len])F(i,1,len-(1<<j)+1)f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
// F(i,1,len)cout<<sa[i]<<" ";cout<<endl;
// F(i,1,len)cout<<rk[i]<<" ";cout<<endl;
// F(i,1,len)cout<<hei[i]<<" ";cout<<endl;
}
int vis[330],_n;
I solve(int l,int r,int w){
// cout<<"!"<<l<<" "<<r<<" "<<w<<endl;
F(i,0,w)vis[i]=0;
F(i,l,r)F(j,p[i].x,p[i].y)vis[j]=1;
F(x,0,w-1)if(vis[x]){
_n=(n-x)/w;
F(i,0,_n)h[i][0]=x+i*w;
F(j,1,lg[_n+1])F(i,0,_n-(1<<j)+1)h[i][j]=ckmin(h[i][j-1],h[i+(1<<(j-1))][j-1]);
F(i,l,r)if(p[i].x<=x&&x<=p[i].y&&p[i].r>=x)ans[p[i].id]=ckmin(ans[p[i].id],ques_min(max(0,(p[i].l-x+w-1)/w),(p[i].r-x)/w));
}
// cout<<"!"<<p[i].id<<" "<<p[i].l<<" "<<p[i].r<<" "<<w<<" "<<x<<" "<<max(0,(p[i].l-x+w-1)/w)<<" "<<max(0,(p[i].r-x)/w)<<endl,
// cout<<"#";
}
int main(){
scanf("%s %s",s+1,t+1);n=strlen(s+1);m=strlen(t+1);read(q);
lg[0]=-1;F(i,1,Mx)lg[i]=lg[i>>1]+1;
F(i,1,q){
read(p[i].l);read(p[i].r);read(p[i].k);read(p[i].x);read(p[i].y);p[i].id=i;ans[i]=-1;
}
sort(p+1,p+1+q);
build_sa();
// while(1){
// int x,y;read(x);read(y);cout<<bbb(x,y)<<endl;
// }
F(i,0,n)xu[i]=i;sort(xu,xu+1+n,bbb);
// F(i,0,n)cout<<xu[i]<<" ";cout<<endl;
F(i,0,n)rak[xu[i]]=i;
F(i,0,n)g[i][0]=i;
F(j,1,lg[n+1])F(i,0,n-(1<<j)+1)g[i][j]=ckmin(g[i][j-1],g[i+(1<<(j-1))][j-1]);
L=1;
F(i,1,q){
if(p[i].k>N){
F(j,(p[i].l-p[i].x)/p[i].k,(p[i].r-p[i].x+p[i].k-1)/p[i].k){
L=max(p[i].l,j*p[i].k+p[i].x),R=min(p[i].r,j*p[i].k+p[i].y);
if(L<=R)ans[p[i].id]=ckmin(ans[p[i].id],ques(L,R));
}
continue;
}
if(p[i].k==p[i+1].k)continue;
solve(L,i,p[i].k);L=i+1;
}
F(i,1,q)printf("%d ",ans[i]);
return 0;
}
/*
arjqmnlntv odkjqehmil 10
5 10 8 0 5
4 10 6 3 4
7 9 7 2 2
0 8 1 0 0
4 7 1 0 0
0 7 7 0 1
2 8 2 1 1
3 5 8 0 0
5 9 2 0 1
1 7 4 1 3
swquopwbur wociakyvje 10
4 8 9 5 6
1 9 5 1 3
4 6 10 4 6
5 7 4 2 3
7 9 8 1 5
7 10 6 0 2
5 8 10 5 7
0 0 6 0 4
3 6 3 2 2
0 6 3 2 2
*/