内网传送门
【题目分析】
菜的只能打线段树拿60滚粗。。。。。CGL太巨了!!!!AK爷啊!!!!
考虑一个合法区间,那么区间gcd一定为区间最小值,所以60pts线段树做法就很脑残了。
然后因为没有修改操作就用ST表可以得80(但我不会啊QAQ)
考虑再转化一下,合法区间内所有数一定为最小值的倍数,所以相当于维护是一个数倍数的区间,最后取最大值即可。
【代码~】
#include<bits/stdc++.h>
using namespace std;
const int MAXN=5e5+10;
int n,top,len,cnt;
int a[MAXN];
int l[MAXN],r[MAXN];
int ans[MAXN];
int vis[MAXN];
int Read(){
int i=0,f=1;
char c;
for(c=getchar();(c>'9'||c<'0')&&c!='-';c=getchar());
if(c=='-')
f=-1,c=getchar();
for(;c>='0'&&c<='9';c=getchar())
i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
struct mstack{
int id,x;
}s[MAXN];
int main(){
n=Read();
for(int i=1;i<=n;++i)
a[i]=Read();
for(int i=1;i<=n;++i){
while(top&&a[i]%s[top].x){
r[s[top].id]=i-1;
top--;
}
s[++top].id=i,s[top].x=a[i];
}
while(top){
r[s[top--].id]=n;
}
for(int i=n;i>=1;--i){
while(top&&a[i]%s[top].x){
l[s[top].id]=i+1;
top--;
}
s[++top].id=i,s[top].x=a[i];
}
while(top){
l[s[top--].id]=1;
}
for(int i=1;i<=n;++i){
if(r[i]-l[i]==len&&!vis[l[i]])
vis[l[i]]=1,ans[++cnt]=l[i];
if(r[i]-l[i]>len){
cnt=1;
vis[l[i]]=1;
ans[cnt]=l[i];
len=r[i]-l[i];
}
}
cout<<cnt<<" "<<len<<'\n';
for(int i=1;i<=cnt;++i)
cout<<ans[i]<<" ";
return 0;
}