4378. 选取数对

题目链接

4378. 选取数对

给定一个长度为 \(n\) 的整数数列 \(a_{1}, a_{2}, \ldots, a_{n}\)
请你选择 \(k\) 个数对 \(\left[l_{1}, r_{1}\right],\left[l_{2}, r_{2}\right], \ldots,\left[l_{k}, r_{k}\right]\) ,要求所选数对满足:

  1. \(1 \leq l_{1} \leq r_{1}<l_{2} \leq r_{2}<\ldots<l_{k} \leq r_{k} \leq n_{\text {。 }}\)
  2. 对于 \(1 \leq i \leq k\)\(r_{i}-l_{i}+1=m\) 均成立。
  3. \(s u m=\sum_{i=1}^{k} \sum_{j=l_{i}}^{r_{i}} a_{j}\) , sum 的值应尽可能大。

请你输出 \(sum\) 的最大可能值。

输入格式

第一行包今三整数 \(n, m, k_{\text {。 }}\)
第二行包含 \(n\) 个整数 \(a_{1}, a_{2}, \ldots, a_{n}\)

输出格式

一个整数,表示 \(s u m\) 的最大可能值。

数据范围

\(6\) 个测试点满足 \(1 \leq m \times k \leq n \leq 20\)
所有测试点满足 \(1 \leq m \times k \leq n \leq 5000 , 0 \leq a_{i} \leq 10^{9}\)

输入样例1:

5 2 1
1 2 3 4 5

输出样例1:

9

输入样例2:

7 1 3
2 10 7 18 5 33 0

输出样例2:

61

解题思路

dp

  • 状态表示:\(f[i][j]\) 表示前 \(i\) 个数,选了 \(j\) 对区间的最大区间和
  • 状态计算:\(f[i][j]=max(f[i-1][j],f[i-m][j-1]+s[i]-s[i-m])\)

分析:第 \(i\) 个数要么在区间内要么不在

  • 时间复杂度:\(O(nk)\)

代码

// Problem: 选取数对
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/4381/
// Memory Limit: 256 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=5005;
int n,m,k,f[N][N],s[N];
int main()
{
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++)
    {
    	cin>>s[i];
    	s[i]+=s[i-1];
    }
    for(int i=m;i<=n;i++)
    	for(int j=1;j<=k;j++)
    		f[i][j]=max(f[i-1][j],f[i-m][j-1]+s[i]-s[i-m]);
    cout<<f[n][k];
    return 0;
}
posted @ 2022-03-20 22:02  zyy2001  阅读(33)  评论(0编辑  收藏  举报