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

Posted ITAK

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了牛客网NOIP赛前集训营-提高组(第四场)B 区间(单调优化)相关的知识,希望对你有一定的参考价值。

传送门
链接:https://www.nowcoder.com/acm/contest/175/B
来源:牛客网

题目描述
给出一个序列 a1, …, an。
定义一个区间 [l,r] 是好的,当且仅当这个区间中存在一个 i,使得 ai 恰好等于 al, al+1, …, ar-1, ar 的最大公因数。
求最长的好的区间的长度。

输入描述:
第一行 n,表示序列的长度;

第二行 n 个数 a1,a2,…,an。
输出描述:
输出一行一个数,表示最长的好的区间的长度。
示例1
输入
复制
5
4 6 9 3 6
输出
复制
4
说明
选择区间 [2,5],i=4。
备注:
对于测试点 1、2,n≤ 100;

对于测试点 3、4,n≤ 2,000;

对于测试点 5、6,n ≤ 200,000, ai≤ 100,且数据随机;

对于测试点 7、8、9,n ≤ 200,000;

对于测试点 10,没有特殊限制。

对于所有数据,n≤ 4x 10^6, 1≤ ai≤ 10^18。

解题思路:

根据题意,那么我们枚举一个 a i a_i ai作为最大公约数,以 i i i 为中心,分别往左和往右找对 a i = = 0 a_i==0 ai==0 的数字,然后我们记录一下长度,代码如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 4e6+5;
LL a[MAXN];
int main()

    int n; cin>>n;
    for(int i=0; i<n; i++) cin>>a[i];
    int ans = 1;
    for(int i=0; i<n; i++)
    
        int l = i, r = i;
        for(int j=i+1; j<n; j++)
        
            if(a[j]%a[i] == 0) r = j;
            else break;
        
        for(int j=i-1; j>=0; j--)
        
            if(a[j]%a[i] == 0) l = j;
            else break;
        
        ans = max(ans, r-l+1);
    
    cout<<ans<<endl;
    return 0;

但是这个复杂度太高,只能过 60 % 60\\% 60% 的数据,因为数据全随机,所以可以过测试点5、6,那么我们来优化一下复杂度,我们发现这个是有单调性的,我们在枚举 a i a_i ai 的时候,不需要每个数都枚举,如果 a j % a i = = 0 a_j\\%a_i==0 aj%ai==0 的话,那么最大公约数为 a i a_i ai 的区间长度一定比最大公约数为 a j a_j aj 的区间长度长,所以我们向右枚举的时候,下标 i i i 不用每次都加1,直接跳到右侧第一个对 % a i ! = 0 \\%a_i!=0 %ai!=0 的下标的位置即可,这样的时间复杂度是 O ( n ) O(n) O(n) 的。

代码如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 4e6+5;
LL a[MAXN];
int main()

    ios::sync_with_stdio(false); cout.tie(0); cin.tie(0);
    int n; cin>>n;
    for(int i=0; i<n; i++) cin>>a[i];
    int ans = 1;
    for(int i=0; i<n; )
    
        int l = i, r = i;
        for(int j=i+1; j<n; j++)
        
            if(a[j]%a[i] == 0) r = j;
            else break;
        
        for(int j=i-1; j>=0; j--)
        
            if(a[j]%a[i] == 0) l = j;
            else break;
        
        i = r+1;
        ans = max(ans, r-l+1);
    
    cout<<ans<<endl;
    return 0;


以上是关于牛客网NOIP赛前集训营-提高组(第四场)B 区间(单调优化)的主要内容,如果未能解决你的问题,请参考以下文章

牛客网 2018年全国多校算法寒假训练营练习比赛(第四场)

2017.10.28noip赛前集训 | T1 差分

2023牛客寒假算法基础集训营

牛客网NowCoder 2018年全国多校算法寒假训练营练习比赛(第四场)A.石油采集(dfs) B.道路建设(最小生成树prim) C.求交集(暴力) F.Call to your teacher

2022牛客寒假算法基础集训营 4 全部题解

2022牛客寒假算法基础集训营 4 全部题解