P9032 [COCI2022-2023#1] Neboderi
可以发现,如果固定 ,那么 显然单调递减。
接着可以发现, 固定时,随着 的增大, 的不同个数并不多。
可以这样理解:如果 不同个数很多,那就意味着每次增大 的时候, 分解质因数后都会有一个质因数的次数变小。而质因数的次数变小很快就会变回 。
所以固定 ,二分 的变化点即可并且 ST 表维护区间 即可。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <numeric>
#include <vector>
using namespace std;
const int N = 1e6 + 5;
int n, k, a[N];
long long ans = 0, sum[N];
int f[N][31], LG2[N];
void Init()
{
LG2[1] = 0;
for (int i = 2; i < N; i++) LG2[i] = LG2[i >> 1] + 1;
for (int i = 1; i <= n; i++)
{
f[i][0] = a[i];
}
for (int j = 1; j <= LG2[n]; j++)
{
for (int i = 1; i + (1 << j) - 1 <= n; i++)
{
f[i][j] = gcd(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
}
}
}
int query(int l, int r)
{
int x = LG2[r - l + 1];
return gcd(f[l][x], f[r - (1 << x) + 1][x]);
}
int main()
{
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]), sum[i] = sum[i - 1] + a[i], ans = max(ans, 1LL * a[i]);
Init();
for (int i = 1; i <= n - k + 1; i++)
{
int nowres = a[i], p = i;
while (p <= n)
{
int l = p + 1, r = n, rr = 0;
while (l <= r)
{
int mid = l + r >> 1;
int gc = query(i, mid);
if (gc >= nowres)
{
l = mid + 1;
}
else
{
r = mid - 1;
rr = mid;
}
}
if (rr == 0) break;
nowres = query(i, rr);
p = rr - 1;
if (p - i + 1 >= k)
{
ans = max(ans, (sum[p] - sum[i - 1]) * (long long)(query(i, rr - 1)));
//printf("%d %d\n", i, p);
}
p = rr;
}
ans = max(ans, (sum[n] - sum[i - 1]) * query(i, n));
}
printf("%lld\n", ans);
return 0;
}

浙公网安备 33010602011771号