4418. 选元素

题目链接

4418. 选元素

给定一个长度为 n 的整数序列 a1,a2,,an

请你从中挑选 x 个元素,要求:

  1. 原序列中的每一个长度为 k 的连续子序列都至少包含一个被选中的元素。
  2. 满足条件 1 的前提下,所选 x 个元素的相加之和应尽可能大。
    输出最大可能和。

输入格式

第一行包含三个整数 n,k,x

第二行包含 n 个整数 a1,a2,,an

输出格式

如果无法满足题目要求,则输出 1

否则,输出一个整数,表示所选元素的最大可能和。

数据范围

前三个测试点满足 1k,xn6
所有测试点满足 1k,xn2001ai109

输入样例1:

5 2 3 5 1 3 10 1

输出样例1:

18

输入样例2:

6 1 5 10 30 30 70 10 10

输出样例2:

-1

输入样例3:

4 3 1 1 100 1 1

输出样例3:

100

解题思路

dp

  • 状态表示:f[i][j] 表示前 i 个数且选了第 i 个数,共选了 j 个数的最大和

  • 状态计算:f[i][j]=max({f[t][j1]})+a[i],其中 itk

  • 时间复杂度:O(n3)

单调队列优化dp

相当于在 t[max(0,ik),i) 范围内找 f[t][j1] 的最大值,其中 j1 固定,将其放在外层循环即可,问题及转化为滑动窗口找最大值问题,每次外层循环注意将 0 放入队列中,因为 0 可能会用到

  • 时间复杂度:O(n2)

代码

// Problem: 选元素 // Contest: AcWing // URL: https://www.acwing.com/problem/content/4421/ // 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=205; int n,k,x; int a[N]; LL f[N][N]; int main() { help; cin>>n>>k>>x; for(int i=1;i<=n;i++)cin>>a[i]; memset(f,-0x3f,sizeof f); f[0][0]=0; for(int i=1;i<=n;i++) for(int j=1;j<=x;j++) for(int t=max(0,i-k);t<i;t++) f[i][j]=max(f[i][j],f[t][j-1]+a[i]); LL res=-1; for(int i=n-k+1;i<=n;i++) res=max(res,f[i][x]); cout<<res; return 0; }
  • 单调队列优化
// Problem: 选元素 // Contest: AcWing // URL: https://www.acwing.com/problem/content/4421/ // 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=205; int n,k,x,a[N]; LL f[N][N]; int main() { scanf("%d%d%d",&n,&k,&x); for(int i=1;i<=n;i++)scanf("%d",&a[i]); memset(f,-0x3f,sizeof f); f[0][0]=0; for(int i=1;i<=x;i++) { deque<int> q; q.pb(0); for(int j=1;j<=n;j++) { if(q.size()&&j-1-q.front()+1>k)q.pop_front(); f[j][i]=f[q.front()][i-1]+a[j]; while(q.size()&&f[q.back()][i-1]<f[j][i-1])q.pop_back(); q.push_back(j); } } LL res=-1; for(int i=n-k+1;i<=n;i++)res=max(res,f[i][x]); printf("%lld",res); return 0; }

__EOF__

本文作者acwing_zyy
本文链接https://www.cnblogs.com/zyyun/p/16244195.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zyy2001  阅读(36)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示