题目描述
给定正整数序列 。
对于区间 ,我们称 ()关于 是 ,当且仅当:。
对于 ,定义 表示:所有 关于 是好的区间中, 的最大值。
对于 ,求出 。
题目分析
利用 ST 表我们可以做到以 的代价查询区间最大公约数。
note
注意到 中的元素的最大公约数是 ,其中 。这等价于 中的元素最大公约数是 和 中的元素最大公约数是 。
现在,我们考虑区间 的区间元素最大公约数是 , 的最大值。 显然具有单调性,可以二分求出 的最大值。同理可求得区间 中 的最小值。
时间复杂度
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int n, h[N];
int f[N][20];
int query(int x, int y) {
int k = log(y - x + 1) / log(2);
return __gcd(f[x][k], f[y - (1 << k) + 1][k]);
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> h[i];
f[i][0] = h[i];
}
// 预处理 ST 表
int t = log(n) / log(2) + 1;
for (int k = 1; k <= t; k++) {
for (int i = 1; i <= n - (1 << k) + 1; i++) {
f[i][k] = __gcd(f[i][k - 1], f[i + (1 << k - 1)][k - 1]);
}
}
for (int i = 1; i <= n; i++) {
int a = , b = i;
(a < b) {
mid = a + b >> ;
((mid, i) < h[i]) a = mid + ;
b = mid;
}
l = a;
a = i, b = n;
(a < b) {
mid = a + b + >> ;
((i, mid) < h[i]) b = mid - ;
a = mid;
}
r = b;
cout << r - l + << ;
}
}