【ST表+二分】codeforces 359 D. Pair of Numbers
题目
https://codeforces.com/problemset/problem/359/D
题解
假设数组 \(a =\) {\(a_1,a_2,...,a_l,...,a_i,...,a_r,...,a_n\)},且 \(a_l, a_{l+1}, ..., a_r(l \leq a_i \leq r)\) 每个数都满足能被 \(a_i\) 整除,那么 \(gcd(a_l,a_{l+1},...a_i,...,a_r) = a_i\) 成立。
核心思路:
- 先用 ST 表预处理出所有(静态)区间 gcd;
- 在第 1 步的基础上,遍历数组 \(a\),枚举以 \(a_i\) 为最大公因数的区间,使用二分法维护出区间的左右端点;
- 在第 2 步维护出所有区间的基础上,维护出区间最大长度,然后筛选出长度为最大长度的所有区间即可。
参考代码
#include<iostream>
#include<vector>
#include<queue>
#include<cmath>using ll = long long;template<typename T, typename E, typename F>
class SparseTable {/*稀疏表*/
private:std::vector<std::vector<E>> dp;F func;
public:SparseTable(T& arr, int arr_size, F func): func(func) {int log2_arr_size = log2(arr_size) + 1;dp.assign(arr_size, std::vector<E>(log2_arr_size));for (int i = 0; i < arr_size; ++ i) dp[i][0] = arr[i];// 初始化第一层for (int j = 1; j < log2_arr_size; ++ j) {// 枚举区间长度 2^jint step = 1 << j;// 区间长度for (int i = 0; i + step - 1 < arr_size; ++ i) {// 枚举区间起点dp[i][j] = func(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]);}}}E query(int l, int r) {// 下标从 0 开始int k = log2(r - l + 1);return func(dp[l][k], dp[r - (1 << k) + 1][k]);}
};int gcd(int a, int b) {return !b ? a : gcd(b, a % b);
}int main() {std::ios::sync_with_stdio(false);std::cin.tie(nullptr);std::cout.tie(nullptr);int n, dis = 0;std::cin >> n;std::vector<int> a(n);std::queue<ll> que;for (int i = 0; i < n; ++ i) std::cin >> a[i];SparseTable<std::vector<int>, int, decltype(&gcd)> st(a, n, gcd);for (int i = 0; i < n; ++ i) {int le = 0, ri = i, md, l, r;while (le < ri) {md = le + ri >> 1;if (a[i] == st.query(md, i)) ri = md;else le = md + 1;}l = le, le = i, ri = n - 1;while (le < ri) {md = le + ri + 1 >> 1;if (a[i] == st.query(i, md)) le = md;else ri = md - 1;}r = le;if (r - l > dis) {que = std::queue<ll>();que.push(1LL * r * n + l);dis = r - l;} else if (que.empty() || r - l == dis && 1LL * r * n + l != que.back()) que.push(1LL * r * n + l);}std::cout << que.size() << ' ' << dis << '\n';while (!que.empty()) {std::cout << (que.front() % n + 1) << ' ';que.pop();}return 0;
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1210525.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!