Description
小H是个善于思考的学生,现在她又在思考一个有关序列的问题。
她的面前浮现出一个长度为n的序列{ai},她想找出一段区间[L, R](1 <= L <= R <= n)。
这个特殊区间满足,存在一个k(L <= k <= R),并且对于任意的i(L <= i <= R),ai都能被ak整除。这样的一个特殊区间 [L, R]价值为R - L。
小H想知道序列中所有特殊区间的最大价值是多少,而有多少个这样的区间呢?这些区间又分别是哪些呢?你能帮助她吧。
Input
第一行,一个整数n.
第二行,n个整数,代表ai.
Output
第一行两个整数,num和val,表示价值最大的特殊区间的个数以及最大价值。
第二行num个整数,按升序输出每个价值最大的特殊区间的L.
Sample Input
输入1: 5 4 6 9 3 6 输入2: 5 2 3 5 7 11
Sample Output
输出1: 1 3 2 输出2: 5 0 1 2 3 4 5
Data Constraint
30%: 1 <= n <= 30 , 1 <= ai <= 32.
60%: 1 <= n <= 3000 , 1 <= ai <= 1024.
80%: 1 <= n <= 300000 , 1 <= ai <= 1048576.
100%: 1 <= n <= 500000 , 1 <= ai < 2 ^ 31.
题解:
暴力打标记。
易证:O(n)
#include<bits/stdc++.h>
#define N 500010
#define inf 2147483647
#define rint register int
#define ll long long
#define point(a) multiset<a>::iterator
#define mod (ll)(500000)
#define mem(a,b) memset(a,b,sizeof (a))
#define open(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
using namespace std;
struct interval
{
int x,y;
}s[N];
int n,ans,i;
int bz[N],l,r,a[N],num,flag[N];
void right_updata()
{
while(r<n && a[r+1] % a[i] == 0)++r,bz[r]=i; }
void left_updata(int k)
{
while(l>1 && a[l-1] % a[i] == 0)--l;
}
int main()
{
open("number");
scanf("%d",&n);
for(i=1;i<=n;i++)scanf("%d",&a[i]);
mem(bz,0);
for(i=1;i<=n;++i)
if(!bz[i])
{
l=r=i;
right_updata();
//确定r
left_updata(a[i]);
//确定l,更新前面的区间.
s[i].x=l,s[i].y=r,bz[i]=i;
}
ans=0;
for(i=1;i<=n;i++)ans=max(ans,s[i].y -s[i].x);
for(mem(flag,0),i=1;i<=n;i++)if(ans == s[i].y-s[i].x && !flag[s[i].x]) ++num,flag[s[i].x]=1;
printf("%d %d\n",num,ans);
for(mem(flag,0),i=1;i<=n;i++)if(ans == s[i].y - s[i].x && !flag[s[i].x]) printf("%d ",s[i].x),flag[s[i].x]=1;
return 0;
}