zoukankan      html  css  js  c++  java
  • 牛客网NOIP赛前集训营-提高组(第四场)B区间

    牛客网NOIP赛前集训营-提高组(第四场)B区间

    题目描述

    给出一个序列$ a_1 dots a_n$。

    定义一个区间 ([l,r]) 是好的,当且仅当这个区间中存在一个 (i),使得 (a_i) 恰好等于 (a_l, a_{l+1} dots a_{r-1}, a_r) 的最大公因数。

    求最长的好的区间的长度。

    输入描述:

    第一行 n,表示序列的长度;
    第二行 n 个数 a1,a2,...,an。
    

    输出描述:

    输出一行一个数,表示最长的好的区间的长度。
    

    乱搞就行,考试的时候睡了一觉就想出来了

    (f[i]) 表示前面第一个能被(a[i])整除的位置

    (g[i]) 表示后面第一个能被(a[i])整除的位置

    则可以递推

    f[1]=1;
    for(int i=2;i<=n;++i){
        if(a[i]%a[f[i-1]]==0)f[i]=f[i-1];
        else f[i]=i;
    }
    g[n]=n;
    for(int i=n-1;i;--i){
    	if(a[i]%a[g[i+1]]==0)g[i]=g[i+1];
    	else g[i]=i;
    }
    

    最后在(f)(g)里面连续的一段取最长的就行了

    但是如果有这种数据:

    5
    10 6 6 6 9
    

    我们写出(f)(g)

    f: 1 2 2 2 5
    g: 1 4 4 4 5
    

    发现有重复数字时位置会不一样

    所以再用两个数组(l[i])(r[i])乱搞一下

    for(int i=1;i<=n;++i)
        r[f[i]]=max(r[f[i]],i),
    	l[g[i]]=min(l[g[i]],i);
    for(int i=1;i<=n;++i)
        r[i]=max(r[i],r[f[i]]),
        l[i]=min(l[i],l[g[i]]);
    for(int i=1;i<=n;++i)ans=max(ans,r[i]-l[i]+1);
    

    注意卡读入,用fread或者ios和tie优化都行

    然后就没有然后了

    可能我的思路比较别致

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 4e6+5;
    #define int long long 
    char getc(){
    	static char buf[maxn],*p1=buf,*p2=buf;
    	return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,maxn,stdin),p1==p2)? EOF:*p1++;
    }
    int mian(){
    	int s=0,f=1;char ch;
    	while(!isdigit(ch=getc()))(ch=='-')&&(f=-1);
    	for(s=ch-'0';isdigit(ch=getc());s=s*10+ch-'0');
    	return s*f;
    }
    int a[maxn],n,f[maxn],g[maxn],ans,l[maxn],r[maxn];
    signed main(){
    	n=mian();
    	for(int i=1;i<=n;++i)a[i]=mian(),l[i]=r[i]=i;
    	f[1]=1;
    	for(int i=2;i<=n;++i){
    		if(a[i]%a[f[i-1]]==0)f[i]=f[i-1];
    		else f[i]=i;
    	}
    	g[n]=n;
    	for(int i=n-1;i;--i)
    		if(a[i]%a[g[i+1]]==0)g[i]=g[i+1];
    		else g[i]=i;
    	for(int i=1;i<=n;++i)
    		r[f[i]]=max(r[f[i]],i),
    		l[g[i]]=min(l[g[i]],i);
    	for(int i=1;i<=n;++i){
    		r[i]=max(r[i],r[f[i]]),
    		l[i]=min(l[i],l[g[i]]);
    	}
    	for(int i=1;i<=n;++i)ans=max(ans,r[i]-l[i]+1);
    	cout<<ans<<endl;
    	return 0;
    }
    

    让我们一起膜拜大佬@olinr

  • 相关阅读:
    Java 深拷贝和浅拷贝 利用序列化实现深拷贝
    算法题005 剑指Offer面试题29 数组中出现次数超过一半的数字
    算法题003 斐波那契(Fibonacci)数列
    Android Sensors (4) 传感器使用最佳实践
    Android WebView使用基础
    Java 多线程(八) 线程状态图
    算法题006 判断两个链表是否相交
    Java 多线程(五) 多线程的同步
    算法题001 剑指Offer 面试题三:二维数组中的查找
    Android绘制基础及手写绘制实例
  • 原文地址:https://www.cnblogs.com/eric-walker/p/9750394.html
Copyright © 2011-2022 走看看