题意:

给定一段长为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. spring-framework-reference(5.1.1.RELEASE)中文版——Core部分

    前言 最近在学习Spring框架,在学习的同时,借助有道翻译,整理翻译了部分文档,由于尚在学习当中,所以该篇文章将会定时更新,目标在一个月左右时间翻译完全部版本. 虽然大部分内容为翻译,但是其中可能会 ...

  2. 启动Nodejs服务

    vs code 中间创建 1.  settings.json { , { , { 'Content-Type': 'text/plain;charset=utf-8' })

  3. 使用OpenCV通过摄像头捕获实时视频并探测人脸

    在Opencv初接触,图片的基本操作这篇手记中,我介绍了一些图片的基本操作,视频可以看作是一帧一帧的图片,因此图片操作其实是视频操作的基础,这篇手记就来讲讲OpenCV中的视频操作,并实现一个用笔记本 ...

  4. sublime c/c++ 环境

    sublime c/c++ 环境 参考: 别人的教程1 别人的教程2 注意,一定要用cmd先试一下,编译成功后再用sublime试 我遇到了一个很诡异的问题,就是cmd运行正常但sublime显示 在 ...

  5. Final发布:文案+美工展示博客

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2476 小组介绍 组长:付佳 组员:张俊余 李文涛 孙赛佳 田良 于洋 段 ...

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

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

  7. c# 写文件注意问题及用例展示

    以txt写string举例,正确代码如下: private void xie() { FileStream fs = new FileStream("1.txt", FileMod ...

  8. P2P通讯原理

    1.简介 当今互联网到处存在着一些中间件(MIddleBoxes),如NAT和防火墙,导致两个(不在同一内网)中的客户端无法直接通信.这些问题即便是到了IPV6时代也会存在,因为即使不需要NAT,但还 ...

  9. 批量梯度下降(BGD)、随机梯度下降(SGD)以及小批量梯度下降(MBGD)的理解

      梯度下降法作为机器学习中较常使用的优化算法,其有着三种不同的形式:批量梯度下降(Batch Gradient Descent).随机梯度下降(Stochastic Gradient Descent ...

  10. koa中接收前台传递的各种数据类型的方式

    标签(空格分隔): koa 数据类型接收 主要介绍三种会用到的中间件,其实都是自己在开发的过程中踩过的坑 首先介绍koa-body [详情介绍 https://github.com/dlau/koa- ...