题意
见数字对
思路
显然满足单调性,所以二分答案,利用
S
T
ST
ST表判断区间最小值和区间
G
C
D
GCD
GCD是否相同。
很不幸,我拿到了85分,发现别人打了
i
n
t
int
int能过???
代码
#include <queue>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define file(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
std::queue<int> q;
int n, ans, num;
int a[500001], logg[500001], fg[500001][20], fm[500001][20];
int check(int len) {
int f = 0;
for (int i = 1; i + len <= n; i++) {
if (std::__gcd(fg[i][logg[len + 1]], fg[i + len - (1 << logg[len + 1]) + 1][logg[len + 1]]) == std::min(fm[i][logg[len + 1]], fm[i + len - (1 << logg[len + 1]) + 1][logg[len + 1]])) {
ans = std::max(ans, len);
if (!f) while (q.size()) q.pop();
f = 1;
q.push(i);
}
}
return f;
}
int main() {
file(point);
scanf("%d", &n);
memset(fm, 127 / 3, sizeof(fm));
logg[0] = -1;
for(int i = 1; i <= n; i++)
logg[i] = logg[i / 2] + 1;
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]), fg[i][0] = fm[i][0] = a[i];
for (int j = 1; j <= 19; j++)
for (int i = 1; i + (1 << j) - 1 <= n; i++) {
fg[i][j] = std::__gcd(fg[i][j - 1], fg[i + (1 << j - 1)][j - 1]);
fm[i][j] = std::min(fm[i][j - 1], fm[i + (1 << j - 1)][j - 1]);
}
int l = 0, r = n;
while (l < r) {
int mid = l + r + 1 >> 1;
if (check(mid - 1)) l = mid;
else r = mid - 1;
}
printf("%d %d\n", q.size(), ans);
for (; q.size(); q.pop())
printf("%d ", q.front());
}