Educational Codeforces Round 69 D. Yet Another Subarray Problem

Educational Codeforces Round 69 (Rated for Div. 2) D. Yet Another Subarray Problem

题目链接

题意:

\(\sum_{i=l}^{r}-k\lceil\frac{r-l+1}{m}\rceil\)的最小值,\(n\leq 3*10^5,m\leq 10\)

思路:

因为\(m\)很小,那么对于一段区间,中间部分可以划分为多个长度为\(m\)的区间,两端都长度不超过\(m\)
所以令\(dp(i)\)表示以\(i\)为终点的区间最小值,那么一种情况是它作为区间终点,另一种情况就是其作为中间的一段,分情况转移即可。
代码如下:

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N = 3e5 + 5;
int n, m, k;
ll a[N], sum[N];
ll dp[N];
int main() {
    ios::sync_with_stdio(false); cin.tie(0);
    cin >> n >> m >> k;
    for(int i = 1; i <= n; i++) cin >> a[i], sum[i] = sum[i - 1] + a[i];
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= min(m, i); j++) {
            dp[i] = max(dp[i], sum[i] - sum[i - j] - k);
        }
        if(i >= m) dp[i] = max(dp[i], dp[i - m] + sum[i] - sum[i - m] - k);
    }
    ll ans = 0;
    for(int i = 1; i <= n; i++) ans = max(ans, dp[i]);
    cout << ans;
    return 0;
}

还有一种算法,因为余数比较小,所以就以\(i\)%\(m\)的值分类,然后对于每个余数维护一个前缀最小值。
更新答案时用目前前缀减去所维护的最小值就行了。

猜你喜欢

转载自www.cnblogs.com/heyuhhh/p/11306747.html