题意:

给定一段长为N的序列,选取其中的至多M段使这些子段和最大。


当N=1000时,我们可以采用动态规划解法

令\(dp[i][j][k]\)代表当前选至位置\(i\)处于第\(j\)段当前是否选取(1选0不选)

则转移为

\(dp[i][j][0]=max(dp[i-1][j][1],dp[i-1][j][0])\)

\(dp[i][j][1]=max(dp[i-1][j-1][0],dp[i-1][j][1])+score[i]\)

其中\(i\)的一维可以滚动掉

Code:

#include <cstdio>
#include <cstring>
int max(int x,int y){return x>y?x:y;}
const int N=503;
const int inf=0x3f3f3f3f;
int dp[N][N][2],n,k,score[N];
void init()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
scanf("%d",score+i);
memset(dp,-0x3f,sizeof(dp));
dp[1][0][0]=0,dp[1][1][1]=score[1];
}
void work()
{
for(int i=2;i<=n;i++)
for(int j=0;j<=k;j++)
{
dp[i][j][0]=max(dp[i-1][j][1],dp[i-1][j][0]);
dp[i][j][1]=max(dp[i-1][j-1][0],dp[i-1][j][1])+score[i];
}
int ans=-inf;
for(int i=0;i<=k;i++)
ans=max(ans,max(dp[n][i][0],dp[n][i][1]));
printf("%d\n",ans);
}
int main()
{
init();
work();
return 0;
}

当N=100,000时,我们可以采用贪心解法

注意到每次选取时,一段连续的正数或者连续的负数,要么我们不取选它,要么全部选走。

我们先缩个点,使序列变成正负数交错的,其中,第一项和最后一项的负数我们一定不去选择,故舍去。

设当前有\(k\)个正数。

则当\(M>=k\)时,直接选取\(k\)个正数即可。

当\(M<=k\)时,对每个正数,我们有两种选择,放弃它,或者跨过负数选择它。

则当选中一个负数\(a\)时,我们损失了\(-a\),当放弃一个正数\(b\)时,我们损失了\(b\)

则不管哪种情况,我们只需要找到绝对值最小的一个数,选择它或者放弃它

采用二叉堆维护这个最小值

当这个最小值被操作时,其实等价于新产生了一个权值为 它和它旁边的两个元素的权值和 的新元素,这时候产生的新数列一定会少一个正数

值得一提的是,当第一项和最后一项是负数的时候,不一定一定减少一个正数,所以我们根据贪心不去选择这些点即可

合并元素可以采用链表进行维护

Code:(实在是不好看QAQ)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#define ll long long
#define P pair <ll,ll>
using namespace std;
const int N=1000010;
ll a[N],b[N],n0,k,n,pre[N],suc[N],cnt,used[N];
ll labs(ll x){return x>0?x:-x;}
void init()
{
scanf("%lld%lld",&n0,&k);
for(int i=1;i<=n0;i++)
scanf("%lld",a+i);
int k=0;a[0]=-1;
while(a[k]<0) k++;
for(int i=k;i<=n0;i++)
{
if(a[i]*a[i-1]>0)
b[n]+=a[i];
else
b[++n]=a[i];
}
while(n&&b[n]<0) n--;
for(int i=1;i<=n;i++)
{
pre[i]=i-1;
suc[i]=i+1;
}
suc[0]=1;
suc[n]=0;
}
priority_queue <P,vector <P >,greater <P > > q;
P p;
void work()
{
for(int i=1;i<=n;i++)
{
if(b[i]>0) cnt++;
p.first=labs(b[i]);
p.second=i;
q.push(p);
}
while(cnt>k)
{
int pos=q.top().second;
q.pop();
if(used[pos]) continue;
if(!suc[pos]&&b[pos]<0)
{
suc[pre[pos]]=suc[pos];
pre[suc[pos]]=pre[pos];
continue;
}
if(!pre[pos]&&b[pos]<0)
{
pre[suc[pos]]=pre[pos];
suc[pre[pos]]=suc[pos];
continue;
}
used[pre[pos]]=used[suc[pos]]=1;
b[pos]+=b[pre[pos]]+b[suc[pos]];
cnt--;
if(pre[pos])
{
pre[pos]=pre[pre[pos]];
suc[pre[pos]]=pos;
}
if(suc[pos])
{
suc[pos]=suc[suc[pos]];
pre[suc[pos]]=pos;
}
p.first=labs(b[pos]),p.second=pos;
q.push(p);
}
int now=suc[0];
ll ans=0;
while(now)
{
if(b[now]>0) ans+=b[now];
now=suc[now];
}
printf("%lld\n",ans);
}
int main()
{
init();
work();
return 0;
}

当N=1,000,000时,我们可以将算法近似优化到\(O(N)\)

具体大家可以参考出题人的题解

我在这里解释一下这个近似,原题解没有说道找到第\(k\)值的问题

主要就是利用基于快速排序思想的STL函数\(nth\_element\),可以在近似\(O(n)\)的复杂度找到第\(k\)值

关于第k值

代码我没写,感觉不太好写

洛谷 P2389 电脑班的裁员 解题报告的更多相关文章

  1. 洛谷P2389 电脑班的裁员(区间DP)

    题目背景 隔壁的新初一电脑班刚考过一场试,又到了BlingBling的裁员时间,老师把这项工作交给了ZZY来进行.而ZZY最近忙着刷题,就把这重要的任务交(tui)给了你. 题目描述 ZZY有独特的裁 ...

  2. 洛谷_Cx的故事_解题报告_第四题70

    1.并查集求最小生成树 Code: #include <stdio.h> #include <stdlib.h>   struct node {     long x,y,c; ...

  3. 洛谷 P2317 [HNOI2005]星际贸易 解题报告

    P2317 [HNOI2005]星际贸易 题目描述 输入输出格式 输入格式: 输出格式: 如果可以找到这样的方案,那么输出文件output.txt中包含两个整数X和Y.X表示贸易额,Y表示净利润并且两 ...

  4. 洛谷 P3802 小魔女帕琪 解题报告

    P3802 小魔女帕琪 题目背景 从前有一个聪明的小魔女帕琪,兴趣是狩猎吸血鬼. 帕琪能熟练使用七种属性(金.木.水.火.土.日.月)的魔法,除了能使用这么多种属性魔法外,她还能将两种以上属性组合,从 ...

  5. 洛谷 P2606 [ZJOI2010]排列计数 解题报告

    P2606 [ZJOI2010]排列计数 题目描述 称一个\(1,2,...,N\)的排列\(P_1,P_2...,P_n\)是\(Magic\)的,当且仅当对所以的\(2<=i<=N\) ...

  6. 洛谷1303 A*B Problem 解题报告

    洛谷1303 A*B Problem 本题地址:http://www.luogu.org/problem/show?pid=1303 题目描述 求两数的积. 输入输出格式 输入格式: 两个数 输出格式 ...

  7. 洛谷 P3084 [USACO13OPEN]照片Photo 解题报告

    [USACO13OPEN]照片Photo 题目描述 农夫约翰决定给站在一条线上的\(N(1 \le N \le 200,000)\)头奶牛制作一张全家福照片,\(N\)头奶牛编号\(1\)到\(N\) ...

  8. 洛谷 P1379 八数码难题 解题报告

    P1379 八数码难题 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初 ...

  9. NOIP2015 D2T3 洛谷2680 BZOJ4326 运输计划 解题报告

    前言:个人认为这是历年NOIP中比较简单的最后一题了,因此将自己的思路与大家分享. 题目大意: 给一棵无根树,给出m条路径.允许将树上的一条边的权值改为0.求m条路径长度最大值的最小值.n,m< ...

随机推荐

  1. JavaScript判断对象是否是NULL(转)

    写js经常会遇到非空判断,看了你不就像风一样的文章 自己没有做总结,特地转载.很有帮助 function isEmpty(obj) { // 检验 undefined 和 null if (!obj ...

  2. 前端基础css

    CSS主要学习的是选择器和样式属性. 导入css的方式:行内样式,内部样式,外部样式(推荐使用) 行内样式:在标记的style属性中设定CSS样式 <p style="color: g ...

  3. Linux 磁盘与文件系统(EXT2)简介

    Linux 中,一切(或几乎一切)都是文件. 一.Linux 磁盘分区与文件系统 1.1 磁盘分区 磁盘的分区主要分为主分区和扩展分区 1)主分区:总共最多只能有四个主分区: 2)扩展分区:只能有一个 ...

  4. RabbitMQ理论部分

    概念 queue        队列 exchange   交换机 bind          绑定 channel     通道 一个发送消息流程包含上述四个概念.消息经过channel传递给exc ...

  5. (第十周)Beta-2阶段成员贡献分

    项目名:食物链教学工具 组名:奋斗吧兄弟 组长:黄兴 组员:李俞寰.杜桥.栾骄阳.王东涵 个人贡献分=基础分+表现分 基础分=5*5*0.5/5=2.5 成员得分如下: 成员 基础分 表现分 个人贡献 ...

  6. 【Alpha】阶段第九次Scrum Meeting

    [Alpha]阶段第九次Scrum Meeting 工作情况 团队成员 今日已完成任务 明日待完成任务 刘峻辰 编写获得所有学院接口 登出接口 赵智源 编写alpha版后测试点测试用例 编写脚本实现测 ...

  7. java 实验1

    北京电子科技学院(BESTI) 实     验    报     告 课程:Java程序设计 班级:1352 姓名:杨光 学号:20135233 成绩:            指导教师:娄嘉鹏  实验 ...

  8. Chapter 1 概述

    软件分为通用软件和应用软件,具有复杂.不可见和不断变化的特点:从出现到现在共经历了四个重要的发展阶段,但现在的软件发展依然存在着许多问题. 软件工程是采用工程的概念.原理.技术和方法来开发与维护软件, ...

  9. 可视化实时Web日志分析工具-goaccess

    说到web服务器就不得不说Nginx,目前已成为企业建站的首选.但由于种种历史原因,Nginx日志分析工具相较于传统的apache.lighthttp等还是少很多. 今天就和大家分享一个非常强大的实时 ...

  10. git 提交本地文件,删除文件夹,修改文件等

    1. 下载git工具包 链接: https://git-scm.com/download/win 2. 右键打开git bash 登陆到自己的github账户 $ git config --globa ...