zoukankan      html  css  js  c++  java
  • 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
    */
    
  • 相关阅读:
    windows下mysql数据库导入导出
    比较两个数组,根据id删除相同的对象
    angular子组件给父组件传值
    angular父组件给子组件传值
    angular获取dom节点
    angular创建服务
    forEach和for包含异步调用的区别
    用某种符号或字符替换某些字符
    嵌套函数和闭包
    JavaScript 递归
  • 原文地址:https://www.cnblogs.com/Purple-wzy/p/13264260.html
Copyright © 2011-2022 走看看