input:interval.in output:interval.out

时间限制: 2000 ms 空间限制: 524288 KB

题目描述

有一个长度为N的序列a[1],a[2]…a[N]。对于一个包含a[L],a[L+1]…a[R]的区间[L,R],小W认为如果存在一个位置a[K]满足区间内所有的数都是a[K]的倍数,那么这个区间是合法的,并且这个区间的价值为R-L,否则这个区间是不合法的。现在小W想知道所有合法的区间中价值最大的区间价值是多少,并且你要告诉他这些区间的左端点(如果有多个区间的价值等于最大值,那么你需要告诉他所有的左端点)。

输入

第一行一个数N,表示数的个数。
第二行N个空格隔开的正整数,表示a[1],a[2]…a[N]。

输出

第一行两个数x,y,分别表示价值最大的区间的个数以及最大价值。
第二行若干个由空格隔开的整数,从小到大输出价值最大的区间的左端点。

样例输入

1
2
3
4
5
6
7
8
9
【样例输入1】
5
4 6 9 3 6

【样例输入2】
30
15 15 3 30 9 30 27 11 5 15 20 10 25 20 30 15 30 15 25 5 10 20 7 7 16 2 7 7 28 7


样例输出

1
2
3
4
5
6
7
【样例输出1】
1 3
2
【样例输出2】
1 13
9

数据范围限制

对于30%的数据,满足N<=30,a[i]<=50
对于70%的数据,满足N<=3000,a[i]<=2000
对于100%的数据,满足N<=300000,a[i]<=2000000

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <bits/stdc++.h>
using namespace std;
#define mod 1000000007
#define ll long long
const int N = 300010;
int n;
int a[N];
int ans1, ans2;
int ans[N];
int main()
{
freopen("interval.in", "r", stdin);
freopen("interval.out", "w", stdout);
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
for (int k = 1; k <= n; k++)
{
int l, r;
for (l = k; l >= 1; l--)
if(l == 1 || a[l - 1] % a[k] != 0)
break;
for (r = k; r <= n; r++)
if(r == n || a[r + 1] % a[k] != 0)
break;
if(ans2 < (r - l))
{
ans1 = 1;
ans[ans1] = l;
ans2 = r - l;
}
else
{
if(ans2 == (r - l))
{
ans[++ans1] = l;
}
}
}
sort(ans + 1, ans + 1 + ans1);
ans1 = unique(ans + 1, ans + 1 + ans1) - (ans + 1);
printf("%d %d\n", ans1, ans2);
for (int i = 1; i <= ans1; i++)
printf("%d ", ans[i]);
return 0;
}