1. 程式人生 > >【NOIP 校內模擬】T1 優美的序列(二分+st表+卡常)

【NOIP 校內模擬】T1 優美的序列(二分+st表+卡常)

我是菜雞 我是蒟蒻 我好菜

ak一定是區間最小的值,且是所有數(包括自己)的最大公約數

我沒看出來 沒救了 noip爆零了 回家養豬了 沒學上了 怎麼辦

gcd有單調性 gcd有單調性 gcd有單調性 gcd有單調性 gcd有單調性 可以二分 可以二分 可以二分 可以二分 要說多少遍才記得到

我沒想到 沒救了 noip爆零了 回家養豬了 沒學上了 怎麼辦

stl少用 stl少用 stl少用 stl少用 要說多少遍

我忘了 沒救了 noip爆零了 回家養豬了 沒學上了 怎麼辦

#include<bits/stdc++.h>
#define N 500005
#define re register 
using namespace std;
int n,a[N],gcd[N][21],maxd;
vector<int> ans;
inline int calc(int a,int b)
{
    re int t;
    while (b)
        t=a,a=b,b=t%b;  
    return a;
}
int LOG[N];
void init()
{
    LOG[0]=-1; 
    for(re int i=1;i<=n;++i)    gcd[i][0]=a[i],LOG[i]=LOG[i/2]+1;
    for(re int j=1;j<=21;++j)
    {
        for(re int i=1;i+(1<<j)-1<=n;++i)
            gcd[i][j]=calc(gcd[i][j-1],gcd[i+(1<<(j-1))][j-1]);
    }
}
inline int query(int l,int r)
{
    int k=LOG[r-l+1];
    return calc(gcd[l][k],gcd[r-(1<<k)+1][k]);
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(NULL);cout.tie(NULL);
    cin>>n;
    for(re int i=1;i<=n;++i)    cin>>a[i];
    init();
    for(re int i=1;i<=n;++i)    //列舉最小的 
    {
        re int l=1,r=i,mid;
        re int ans1=i,ans2=i;
        while(l<=r)
        {
            mid=(l+r)>>1;
            if(query(mid,i)==a[i])  ans1=mid,r=mid-1;
            else l=mid+1;
        }
        l=i,r=n;
        while(l<=r)
        {
            mid=(l+r)>>1;
            if(query(i,mid)==a[i])  ans2=mid,l=mid+1;
            else r=mid-1;
        }
        if(ans2-ans1==maxd) ans.push_back(ans1);
        if(ans2-ans1>maxd)  ans.clear(),maxd=ans2-ans1,ans.push_back(ans1);
    }
    vector<int>::iterator it=unique(ans.begin(),ans.end());
    cout<<it-ans.begin()<<" "<<maxd<<'\n';
    for(re vector<int>::iterator i=ans.begin();i!=it;++i)   cout<<*i<<' ';
}