题解 P5502 【[JSOI2015]最大公约数】
wlzhouzhuan · · 题解
- 前言
对于这类求一段区间的权值
- 题解
我们考虑将
显然,重点是如何合并两段区间,找出更优的答案。
我们采用类似归并排序的思路,在归并排序的时候,由于需要采取数从小到大的原则,所以我们的
类比过来,对于此题已知了
- 代码
%:pragma GCC optimize(2)
%:pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define lll __int128
const int N = 100005;
ll a[N];
int n;
ll gcd(ll x, ll y) {
return y ? gcd(y, x % y) : x;
}
ll dfs(int l, int r) {
if (l == r) return a[l];
int mid = (l + r) >> 1;
ll ans = max(dfs(l, mid), dfs(mid + 1, r));
ll g = gcd(a[mid], a[mid + 1]);
ans = max(ans, 2LL * g);
int x = mid, y = mid + 1;
while (x > l && y < r) {
if (gcd(g, a[x - 1]) > gcd(g, a[y + 1])) {
g = gcd(g, a[x - 1]); x--;
}
else {
g = gcd(g, a[y + 1]); y++;
}
ans = max(ans, (ll)(y - x + 1) * g);
}
while (x > l) {
g = gcd(g, a[x - 1]); x--;
ans = max(ans, (ll)(y - x + 1) * g);
}
while (y < r) {
g = gcd(g, a[y + 1]); y++;
ans = max(ans, (ll)(y - x + 1) * g);
}
return ans;
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%lld", &a[i]);
}
printf("%lld\n", dfs(1, n));
return 0;
}
- 后记
我曾经做过一道题目,题面是求
读者可以考虑一下,此时我们的
题目可在我私人团队里提交,跳转链接 : 区间Max
也贴下代码,供读者理解:
%:pragma GCC optimize(2)
%:pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define lll __int128
#define dd double
#define _i int
#define RE register
#define rep(i, l, r) for (RE int i = l; i <= r; i++)
#define req(i, l, r) for (RE int i = l; i >= r; i--)
#define range(i, l, r) rep(i, l, r - 1)
#define Be(s, t) memset(s, t, sizeof(s))
#define poly vector <int>
#define pii pair <int, int>
template <typename T> void read(T &x) { x = 0; int FF = 1; char op = getchar(); while (!isdigit(op)) { if (op == '-') FF = -1; op = getchar(); } while (isdigit(op)) { x = (x << 1) + (x << 3) + op - '0'; op = getchar(); } x *= FF; }
template <typename T> void print(T x) { if (x < 0) { putchar('-'); x = -x; } if (x < 1) return ; print(x / 10); putchar(x % 10 + '0'); }
template <typename T> void print(T x, char _tab) { print(x); putchar(_tab); }
const int N = 500005;
ll a[N];
int n;
ll dfs(int l, int r) {
if (l == r) return a[l];
int mid = (l + r) >> 1;
ll ans = max(dfs(l, mid), dfs(mid + 1, r));
ll x = mid, y = mid + 1, h = min(a[x], a[y]);
ans = max(ans, 2 * h);
while (x > l && y < r) {
if (a[x - 1] < a[y + 1]) h = min(h, a[++y]);
else h = min(h, a[--x]);
ans = max(ans, (ll)(y - x + 1) * h);
}
while (x > l) {
h = min(h, a[--x]);
ans = max(ans, (ll)(y - x + 1) * h);
}
while (y < r) {
h = min(h, a[++y]);
ans = max(ans, (ll)(y - x + 1) * h);
}
return ans;
}
int main() {
read(n);
rep(i, 1, n) read(a[i]);
print(dfs(1, n), '\n');
return 0;
}