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
*/
原文地址:https://www.cnblogs.com/Purple-wzy/p/13264260.html