区间

给定一个序列,定义一个区间为「好」当区间中存在一个数是其余元素的最大公因数。求最长「好」区间的长度。输入包含序列长度和序列本身,输出最长区间长度。示例:对于序列[4, 6, 9, 3, 6],最长「好」区间长度为4。题目分为多个测试点,对n和ai有不同的限制。90分解决方案采用O(nlogn)复杂度,而100分解决方案则为线性时间复杂度。" 78431186,5750772,HBase Java API:禁用与启用表操作,"['HBase', '数据库管理', 'Java开发']
摘要由CSDN通过智能技术生成

题目描述

给出一个序列 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 1 0 6 10^6 106, 1≤ ai≤ 1 0 1 8 10^18 1018

90分思路:

第一次90分
• 注意到:如果 ? 的区间扩展到了 ?,那么 ? 的区间一定是 ? 的区间的子区间(因为 ? 是 ? 的一个倍

数),从而不可能更新答案

• 我们可以考虑按一个顺序枚举 ?,每次只要一个点被区间经过,就可以不用扩展它的区间

• 按 ?? 从小到大的顺序扩展 ?,这样每一个数最多被扩展过两次(从左和从右分别一次)

• 时间复杂度为排序复杂度 O(nlogn)O(nlogn)
以上是官方给出的部分题解,也就是复杂度较高的题解。
照着思路写了一遍得到了90分。
这里需要注意一个问题,就是这里j被扩展到是有方向的,也就是说如果单纯的将被扩展之后的位置打上标记的话是错误的(虽然仍然能够得到90分,数据水。)
如下面的数据:
5
4 72 36 9 18
我们会先从4开始扩展,那么如果这个时候就给72 和 36打上标记的话,我们再从9扩展的时候就无法扩展到72和36。所以原本最长的答案4就会变成3。
观察怎么解决这个问题,我们考虑如果9在4右边在72和36的左边,那么就会出现4的区间会包括9的区间,那么把vis带上方向判断就可以了。
vis[i][0]vis[i][0]表示i这个位置的点有没有被其左边的点更新过。
vis[i][1]vis[i][1]表示这个位置的点有没有被其右边的点更新过。

90分代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#define int long long
using namespace std;
const int wx=4000017; 
inline char get_char(){
    
    static char buf[1000001],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
#define short long long
inline short read()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值