我是靠谱客的博主 任性纸鹤,最近开发中收集的这篇文章主要介绍Codeforces359 D. Pair of Numbers (二分+rmq(ST表) ),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

题意:

给定长度为n的数组
要求找到若干对L和R,满足以下条件:

  • [L,R]内存在一个数,满足[L,R]的所有数能被这个数整除
  • 使R-L尽量大

输出满足条件的(L,R)对数,以及最大的R-L
还需要输出所有满足条件的数对(L,R)的左端点L

数据范围:n<=3e5

解法:

观察问题条件1:
[L,R]内存在一个数,满足[L,R]的所有数能被这个数整除
想想能整除区间内所有数的数需要满足什么性质?
因为这个数需要能整除区间内所有数,且这个数需要在区间内
那么这个数一定就是这个区间内的最小数
因为这个数整除所有数,且这个数最小,那么这个区间的gcd就等于这个数

综上得满足条件的区间即满足:区间min=区间gcd

R-L尽量大等同于R-L+1尽量大,其实就是区间尽量大
如果存在长度为k的区间满足,那么一定存在长度为k-1的区间也满足
也就是说答案存在单调性,可以二分

二分区间长度然后尺取check就行了
区间min和区间gcd用rmq数据结构来计算就行了

code:

#include<bits/stdc++.h>
using namespace std;
const int N=3e5+5;
int m[N][25],g[N][25],maxd;
int lg2[N];
int a[N],n;
int gcd(int a,int b){
    return b==0?a:gcd(b,a%b);
}
void rmq_init(){
    lg2[1]=0;
    for(int i=2;i<N;i++){//预处理lg2[]
        lg2[i]=lg2[i-1];
        if((i&(i-1))==0)lg2[i]++;
    }
    maxd=lg2[n]+1;
    for(int i=1;i<=n;i++){
        m[i][0]=g[i][0]=a[i];
    }
    for(int j=1;j<=maxd;j++){
        for(int i=1;i+(1<<j)-1<=n;i++){
            m[i][j]=min(m[i][j-1],m[i+(1<<(j-1))][j-1]);
            g[i][j]=gcd(g[i][j-1],g[i+(1<<(j-1))][j-1]);
        }
    }
}
int m_ask(int l,int r){
    int k=lg2[r-l+1];
    return min(m[l][k],m[r-(1<<k)+1][k]);
}
int g_ask(int l,int r){
    int k=lg2[r-l+1];
    return gcd(g[l][k],g[r-(1<<k)+1][k]);
}
bool check(int mid){
    for(int i=1;i<=n;i++){
        int j=i+mid-1;
        if(j>n)break;
        if(m_ask(i,j)==g_ask(i,j)){
            return 1;
        }
    }
    return 0;
}
signed main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    rmq_init();
    int l=1,r=n;
    int ans=1;
    while(l<=r){
        int mid=(l+r)/2;
        if(check(mid))ans=mid,l=mid+1;
        else r=mid-1;
    }
    vector<int>idx;
    for(int i=1;i<=n;i++){
        int j=i+ans-1;
        if(j>n)break;
        if(m_ask(i,j)==g_ask(i,j)){
            idx.push_back(i);
        }
    }
    printf("%d %dn",(int)idx.size(),ans-1);
    for(int v:idx){
        printf("%d ",v);
    }
    return 0;
}

最后

以上就是任性纸鹤为你收集整理的Codeforces359 D. Pair of Numbers (二分+rmq(ST表) )的全部内容,希望文章能够帮你解决Codeforces359 D. Pair of Numbers (二分+rmq(ST表) )所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(42)

评论列表共有 0 条评论

立即
投稿
返回
顶部