LG P2389 电脑班的裁员
Description
ZZY有独特的裁员技巧:每个同学都有一个考试得分$a_i(-1000 \leq a_i \leq 1000)$,在$n$个同学$(n \leq 500)$中选出不大于$k$段$(k \leq n)$相邻的同学留下,裁掉未被选中的同学,使剩下同学的得分和最大。要特别注意的是,这次考试答错要扣分【不要问我为什么】,所以得分有可能为负。
Solution
对于$n^3$复杂度:
设$f(i,j)$表示当前选到第$i$个数,选取的段数$\leq j$的最大价值,$s_i$表示前缀和,可以分类讨论:
- $i$不选,则$f(i,j)=f(i-1,j)$
- $i$选,则$f(i, j)=\max \left\{f(k, j-1)+s_{i}-s_{k}\right\}(k < i)$
对于$n^2$复杂度:
设$g(i,j-1)=f(k,j-1)-s_k$,在更新$f$的时候顺便更新$g$,可以做到$n^2$的复杂度
对于$n^2$复杂度:
还有别的思路:
设$f(i,j)$表示当前选到第$i$个数,选取的段数$\leq j$,且$i$不一定选择的最大价值,$g(i,j)$表示当前选到第$i$个数,选取的段数$\leq j$,且$i$一定选择的最大价值
更新$g$时,需要讨论$i-1$是否选择,更新$f$时,需要讨论$i$是否选择:
$$g(i, j)=\max \{g(i-1, j), f(i-1, j-1)\}+a_{i}$$
$$f(i, j)=\max \{g(i, j), f(i-1, j)\}$$
实现时可以滚动数组省去一维,空间复杂度$O(n)$
对于$n\log n$复杂度:
可以贪心
对于一段连续的符号相同的数,只有全部选择或全部不选择两种情况:
- 如果一段负数只选择了一半,就可以找到更大的价值(不选这段负数)
- 如果一段正数只选择了一半,也可以找到更大的价值(同时选择另一段)
所以可以将所有连续的、符号相同的数融合成一个数
设当前序列中正数的个数为$cnt$
- $cnt \geq k$时,选择最大的$k$个正数
- $cnt < k$时,需要做出一些放弃
要么选择一个负数,将两个正数连接在一起;要么放弃一个正数
不论哪一种选择,选择对数$x$进行操作,损失的价值都为$|x|$
使用优先队列可以实现
对于$n$复杂度:
贪心还可以改进
假设当前还需要合并$m$个数,那么:
- 大小小于第$m$大的必定要被合并
- 大小大于第$3m$大的必定不会被合并
- 每一轮合并至少合并了$\frac m3$个数
每次合并将三个数合并为一个,所以合并$m$个数最多会影响$3m$个数,假如每次影响的三个数大小都为小于第$m$大,就会合并$\frac m3$个数
总时间复杂度:$n+\frac{2}{3} n+\left(\frac{2}{3}\right)^{2} n+\ldots$

#include<algorithm>
#include<iostream>
#include<utility>
#include<cstdio>
#include<queue>
#include<cmath>
using namespace std;
int n,k,l[],r[],l1[],r1[],tot,cnt;
long long ans,a[];
bool del[],del1[],in[];
queue<long long>q;
pair<long long,int>t[],minn,maxx;
inline int read()
{
int f=,w=;
char ch=;
while(ch<''||ch>'')
{
if(ch=='-')
f=-;
ch=getchar();
}
while(ch>=''&&ch<='')
{
w=(w<<)+(w<<)+ch-'';
ch=getchar();
}
return f*w;
}
void delet1(int x)
{
if(x)
{
int L=l1[x],R=r1[x];
l1[R]=L;
l1[L]=R;
del1[x]=true;
}
}
void delet(int x)
{
if(x)
{
--tot;
int L=l[x],R=r[x];
l[R]=L;
r[L]=R;
del[x]=true;
delet1(x);
}
}
void add(int x)
{
if(x&&pair<long long,int>(abs(a[x]),x)<=minn)
{
in[x]=true;
q.push(x);
}
}
void merge(int x)
{
if(del[x])
{
return;
}
int L=l[x],R=r[x];
if(L&&abs(a[L])<abs(a[x]))
{
return;
}
if(R&&abs(a[R])<abs(a[x]))
{
return;
}
delet(L);
delet(R);
a[x]+=a[L]+a[R];
if(L&&R)
{
add(x);
}
else
{
delet(x);
} }
int main()
{
n=read();
k=read();
for(int i=;i<=n;i++)
{
int x=read();
if(!x)
{
continue;
}
if(x<&&!tot)
{
continue;
}
if(tot&&a[tot]<==x<)
{
a[tot]+=x;
}
else
{
a[++tot]=x;
}
}
if(tot&&a[tot]<)
{
--tot;
}
for(int i=;i<=tot;i++)
{
l[i]=l1[i]=(i+tot)%(tot+);
r[i]=r1[i]=(i+)%(tot+);
}
while(tot>k*-)
{
cnt=;
for(int i=r1[];i;i=r1[i])
{
if(!del1[i])
{
t[++cnt]=pair<long long,int>(abs(a[i]),i);
}
}
int temp=(tot-(k*-))>>;
nth_element(t+,t+min(cnt,temp),t+cnt+);
minn=t[min(cnt,temp)];
nth_element(t+,t+min(cnt,*temp),t+cnt+);
maxx=t[min(cnt,*temp)];
for(int i=r1[];i;i=r1[i])
{
pair<long long,int> p(abs(a[i]),i);
if(p>maxx)
{
delet1(i);
}
else
{
add(i);
}
}
while(q.size())
{
int u=q.front();
q.pop();
in[u]=false;
merge(u);
}
}
for(int i=r[];i;i=r[i])
{
if(a[i]>)
{
ans+=a[i];
}
}
printf("%lld\n",ans);
return ;
}
电脑班的裁员
LG P2389 电脑班的裁员的更多相关文章
- 洛谷P2389 电脑班的裁员(区间DP)
题目背景 隔壁的新初一电脑班刚考过一场试,又到了BlingBling的裁员时间,老师把这项工作交给了ZZY来进行.而ZZY最近忙着刷题,就把这重要的任务交(tui)给了你. 题目描述 ZZY有独特的裁 ...
- P2389 电脑班的裁员 (动态规划)
题目背景 隔壁的新初一电脑班刚考过一场试,又到了BlingBling的裁员时间,老师把这项工作交给了ZZY来进行.而ZZY最近忙着刷题,就把这重要的任务交(tui)给了你. 题目描述 ZZY有独特的裁 ...
- 洛谷 P2389 电脑班的裁员 解题报告
题意: 给定一段长为N的序列,选取其中的至多M段使这些子段和最大. 当N=1000时,我们可以采用动态规划解法 令\(dp[i][j][k]\)代表当前选至位置\(i\)处于第\(j\)段当前是否选取 ...
- P2389 电脑班的裁员
题意:长度为n的序列,选出k个连续的字段,使和最大(有负数) 暴力只选正数且不考虑k的边界问题50(数据...) 正解从$O(n^3)到O(n)$不等,($O(n)$不会) DP 1.$O(n^3)$ ...
- 【Luogu】P2389电脑班的裁员(DP)
题目链接 sbt交了三遍才过是我的耻辱…… 就是设f[i][j]搞个三重循环DP一下,以上. #include<cstdio> #include<cstdlib> #inclu ...
- Linux下安装性能测试负载机LG
系统:CentOS release 6.6 (Final) x86_64 安装包: 1.LRLG_00031.iso [Load Generator Standalone (Linux 64-bit ...
- bootstrap 之 xs,sm,md,lg && 主要颜色
mobile – xs ( <768px ) tablet – sm ( 768~991px ) desktop – md ( 992~1170px ) large desktop – lg ( ...
- boostrap中lg,md,sm,xs
boostrap中lg,md,sm,xs分别表示多少px? .col-xs- 超小屏幕 手机 (<768px).col-sm- 小屏幕 平板 (≥768px).col-md- 中等屏幕 桌面显示 ...
- LG 2.2.1 P350安卓系统刷机,问题总结,希望对需要的朋友有助
手机误删软件导致短信,键盘等无声音提醒 我的手机前几天被我误删了一个软件,导致电话接不了,别人打电话的时候,老提示我在通话中,但是我可以在通话中看到对方的打电话记录.短信,键盘,USB连接,等等都没有 ...
随机推荐
- PYTHON-anaconda-安装
1.下载: 官网地址:https://www.anaconda.com/products/individual/get-started 镜像地址(推荐):https://mirrors.tuna.ts ...
- (转)C# 获取当前路径的7中方法
//获取模块的完整路径. string path1 = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName; //获取 ...
- 记一次mysql数据库被勒索(下)
背景: nextcloud的mysql数据库被黑,删库勒索.参考:记一次mysql数据库被勒索(上) mysql数据库恢复成功,nextcloud还是无法连接.参考:记一次mysql数据库被勒索(中) ...
- VMware Workstation 15 Pro安装带图形化界面的CentOS7
1.双击打开“VMware Workstation”,然后选择“创建新的虚拟机” 2.在安装向导中,选择“稍后安装操作系统”,然后点击“下一步”继续安装 3.在“客户机操作系统”中选择“Linux(L ...
- 理解RESTful原理
如何给老婆解释什么是RESTful 老婆经常喜欢翻看我订阅的技术杂志,她总能从她的视角提出很多有趣的问题. 一个悠闲的周日下午,她午觉醒来,又习惯性的抓起这个月的杂志,饶有兴趣地看了起来. 果不其然, ...
- C++ Templates (Part I 基本概念 The Basics)
C++ 模板 (C++ Templates) 目录 C++ 模板 (C++ Templates) 第一部分 基本概念 (The Basics) 第一部分章节目录 参考资料 第一部分 基本概念 (The ...
- 鼠标移上显示的下拉菜单,和鼠标移上时显示的导航,html,JavaScript代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- lombook插件的说明
lombok是一个可以帮助我们简化java代码编写的工具类,尤其是简化javabean的编写,即通过采用注解的方式,消除代码中的构造方法,getter/setter等代码,使我们写的类更加简洁,当然, ...
- count.exe 个人项目
Github项目地址:https://github.com/bravedreamer/wordCount/tree/master/wc 一.题目描述: Word Count1. 实现一个简单而完整的软 ...
- SQL语句中IF的简单使用 - 关联leetcode 627.交换工资
MySQL的IF既可以作为表达式用,也可在存储过程中作为流程控制语句使用,如下是做为表达式使用: IF表达式 IF(expr1,expr2,expr3) 如果 expr1 是TRUE (expr1 & ...