zoukankan      html  css  js  c++  java
  • Jzoj3895 数字对

    给你一个序列s,求出所有最长的区间[l,r]使得存在一个k∈[l,r]且对于任何i∈[l,r]都有s[k]|s[i]

    显然如果这个k存在,那么s[k]一定是s[l]~s[r]的最小值

    现在问题就成了,求一个最长的区间使得s[l]~s[r]的最小值=s[l]~s[r]的gcd

    那么我们可以二分答案,而求一个区间最小和gcd都可以用ST表完成,所以整体复杂度nlg^2n

    (虽然说这是solution的方法但是不是最快的方法,最快的方法是枚举k,让后向两边暴力扫描法,复杂度是n^2的但是跑起来非常快!)

    正解:313ms

    #pragma GCC optimize("O3")
    #pragma G++ optimize("O3")
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<vector>
    using namespace std;
    inline int Min(int a,int b){ return a<b?a:b; }
    inline int gcd(int a,int b){
    	for(int c;b;a=b,b=c) c=a%b;
    	return a;
    }
    int preLog[500010],n,w[500010];
    vector<int> A;
    struct ST_list{
    	int (*f)(int,int) ;
    	int g[20][500010];
    	void init(int* s,int (*f1)(int,int) ){
    		f=f1;
    		memcpy(g[0]+1,s+1,n<<2);
    		for(int i=n;i;--i)
    			for(int j=1;i+(1<<j)-1<=n;++j)
    				g[j][i]=f(g[j-1][i],g[j-1][i+(1<<j-1)]);
    	}
    	int query(int l,int r){
    		int k=preLog[r-l+1];
    		return f(g[k][l],g[k][r-(1<<k)+1]);
    	}
    } s1,s2;
    bool ok(int len){
    	int M=n-len;
    	for(int i=1;i<=M;++i)
    		if(s1.query(i,i+len)==s2.query(i,i+len)) return 1;
    	return 0;
    }
    int main(){
    	preLog[1]=0;
    	for(int i=2,j=0;i<=500010;++i){
    		if(i==(1<<j+1)) ++j;
    		preLog[i]=j;
    	}
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i) scanf("%d",w+i);
    	s1.init(w,Min); s2.init(w,gcd);
    	int l=0,r=n-1;
    	for(int m;l<r;){
    		m=l+r+1>>1;
    		if(ok(m)) l=m;
    		else r=m-1; 
    	}
    	n-=l;
    	for(int i=1;i<=n;++i)
    		if(s1.query(i,i+l)==s2.query(i,i+l)) A.push_back(i);
    	printf("%d %d
    ",A.size(),l);
    	for(int i=0,z=A.size();i<z;++i) printf("%d ",A[i]);
    }
    暴力:76ms

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #define fo(i,a,b) for(int i=a;i<=b;i++)
    #define N 500010
    using namespace std;
    int a[N],ans[N];
    int main()
    {
        int n,num=0,val=0;
        cin>>n;
        fo(i,1,n)
        {
                 scanf("%d",&a[i]);
                 if(a[i]==1)
                 {
                            cout<<1<<' '<<n-1<<endl<<1;
                            return 0;
                 }
        }
        fo(k,1,n)
        {
                 if(a[k]==0) continue;
                 int l=k,r=k;
                 while(a[l-1]%a[k]==0 && l>1) l--;
                 while(a[r+1]%a[k]==0 && r<n) r++;
                 if(r-l==val && l!=ans[num]) ans[++num]=l;
                 if(r-l>val)
                 {
                            fo(i,1,num) ans[i]=0;
                            val=r-l,ans[num=1]=l;
                 }
        }
        cout<<num<<' '<<val<<endl;
        fo(i,1,num) printf("%d ",ans[i]);
    }

  • 相关阅读:
    Scrapy爬虫框架的安装和使用
    pyspider爬虫框架的安装和使用
    Pyquery解析库的安装和使用
    Beautiful Soup解析库的安装和使用
    lxml解析库的安装和使用
    PhantomJS的安装和使用
    GeckoDriver的安装和使用
    用其他主机docker login登录Harbor仓库报错
    强制删除 Terminating 状态的pod
    YUM安装软件提示[Errno 14] curl#6
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/9477339.html
Copyright © 2011-2022 走看看