• [BalticOI 2018]火星人的 DNA


    洛咕

    给定一个字符集大小 (|Sigma| = K) 的长度为 (N) 的字符串和 (R)个要求,每个要求为使子串中的字符 (B) 至少出现 (Q) 次。求出满足所有要求的最短子串长度。

    分析:设(bj[val]=1)表示对val这个数有要求,(tong[val])表示对val这个数要求有多少个,建立两个指针l=1,r=0,不断让r++,并且判断当前的(a[r])是否有要求(被标记),如果有要求,令(tong[a[r]]--),如果剪到了0,说明满足了一个要求,令(R--),找到了一个合法的r(即使得R=0)之后,我们再令l++,判断当前的l减掉之后是否还能满足条件,判断方法跟之前的r加进来之后差不多,如果满足条件,说明l还可以继续增加,区间可以继续变小,如果不满足条件,继续增加r,直到r=n.

    时间复杂度是在(O(n))左右.

    以下两份代码一个是用while实现l的增加,一个是用for循环实现,前者细节较多,代码量也长一点点.后者更好理解,更加优秀.

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define ll long long
    using namespace std;
    inline int read(){
        int x=0,o=1;char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')o=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*o;
    }
    const int N=200005;
    int a[N],tong[N],bj[N];
    int main(){
    	int n=read(),k=read(),R=read();
    	for(int i=1;i<=n;++i)a[i]=read();	
    	for(int i=1;i<=R;++i){
    		int val=read(),num=read();
    		tong[val]=num;bj[val]=1;
    	}
    	int l=1,r=0,ans=n+1;
    	while(1){
    		int BJ=0;
    		while(r<n&&R>0){
    			++r;
    			if(bj[a[r]]){
    				tong[a[r]]-=1;
    				if(tong[a[r]]==0)--R;
    			}
    			if(!R)BJ=1;
    		}
    		if(!BJ)break;
    		ans=min(ans,r-l+1);
    		while(l<r&&!R){
    			++l;
    			if(bj[a[l-1]]){
    				++tong[a[l-1]];
    				if(tong[a[l-1]]<=0)ans=min(ans,r-l+1);
    				else R=1;
    			}
    			else ans=min(ans,r-l+1);
    		}
    	}
    	if(ans==n+1)puts("impossible");
    	else printf("%d
    ",ans);
        return 0;
    }
    
    
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define ll long long
    using namespace std;
    inline int read(){
        int x=0,o=1;char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')o=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*o;
    }
    const int N=200005;
    int a[N],bj[N],tong[N];
    int main(){
    	int n=read(),K=read(),R=read();
    	for(int i=1;i<=n;++i)a[i]=read();
    	for(int i=1;i<=R;++i){
    		int val=read(),sum=read();
    		bj[val]=1;tong[val]=sum;
    	}
    	int ans=n+1;
    	for(int i=1,j=0;i<=n;++i){
    		while(j<n&&R>0){
    			++j;
    			if(bj[a[j]])
    				if(--tong[a[j]]==0)--R;
    		}
    		if(j>=n&&R>0)break;
    		ans=min(ans,j-i+1);
    		if(bj[a[i]])
    			if(++tong[a[i]]==1)++R;
    	}
    	if(ans==n+1)puts("impossible");
    	else printf("%d
    ",ans);
        return 0;
    }
    
    
    
  • 相关阅读:
    hdu 5517 Triple(二维树状数组)
    bzoj 3998: [TJOI2015]弦论(后缀自动机)
    hdu 5008 Boring String Problem(后缀数组+rmq)
    hdu 4622 Reincarnation(后缀自动机)
    hdu 6025 card card card(双指针)
    寒武纪camp Day3
    寒武纪camp Day2
    寒武纪camp Day1
    Codeforces 920G(二分+容斥)
    Codeforces 920E(补图BFS)
  • 原文地址:https://www.cnblogs.com/PPXppx/p/11349620.html
Copyright © 2020-2023  润新知