163. 生日礼物

题目链接

163. 生日礼物

翰翰 18 岁生日的时候,达达给她看了一个神奇的序列 A1,A2,,AN

她被允许从中选择不超过 M 个连续的部分作为自己的生日礼物。

翰翰想要知道选择元素之和的最大值。

你能帮助她吗?

输入格式

第一行包含两个整数 N,M

第二行包含 N 个整数 A1AN

输出格式

输出一个整数,表示答案。

数据范围

1N,M105,
|Ai|104

输入样例:

5 2 2 -3 2 -1 2

输出样例:

5

解题思路

反悔贪心

首先预处理:把所有的正数和负数合并,最后一定是 交替的情况,先把所有的正数放入堆中,如果正数段数不大于要求的段数,则显然全选最优,否则考虑合并或者删除某些已选择的正数,而由于选择负数合并或者删除正数,都要求选择的数的绝对值尽量小,答案才会更大,而且选择的数要求不能相邻,如果选择的数相邻的话,必定是一个正数一个负数的情况,正数表示不选这个正数,负数表示选择这个负数,既然选择负数,选择正数必然更优,即选择的数不能相邻,且选择的所有数最小,即转化为 147. 数据备份 这个问题

  • 时间复杂度:O(nlogn)

代码

// Problem: 生日礼物 // Contest: AcWing // URL: https://www.acwing.com/problem/content/165/ // Memory Limit: 64 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=1e5+5; int n,m,a[N],b[N],cnt,L[N],R[N]; void del(int x) { L[R[x]]=L[x],R[L[x]]=R[x]; } int main() { cin>>n>>m; for(int i=1;i<=n;i++)cin>>a[i]; int st=1,ed=n; while(st<=n&&a[st]<=0)st++; while(ed>=1&&a[ed]<=0)ed--; int t=a[st]; for(int i=st+1;i<=ed;i++) if((LL)t*a[i]>=0)t+=a[i]; else b[++cnt]=t,t=a[i]; b[++cnt]=t; set<PII> s; int res=0,p=0; for(int i=0;i<=cnt+1;i++) { L[i]=i-1,R[i]=i+1; if(b[i]>0)res+=b[i],p++; if(i>=1&&i<=cnt) b[i]=abs(b[i]),s.insert({b[i],i}); } b[0]=b[cnt+1]=2e9; if(m>=p)cout<<res; else { int k=p-m; while(k--) { auto p=s.begin(); int x=(*p).se; res-=b[x]; int l=L[x],r=R[x]; s.erase(p); s.erase({b[l],l}),s.erase({b[r],r}); b[x]=b[l]+b[r]-b[x]; s.insert({b[x],x}); del(l),del(r); } cout<<res; } return 0; }

__EOF__

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