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 电脑班的裁员的更多相关文章

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

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

  2. P2389 电脑班的裁员 (动态规划)

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

  3. 洛谷 P2389 电脑班的裁员 解题报告

    题意: 给定一段长为N的序列,选取其中的至多M段使这些子段和最大. 当N=1000时,我们可以采用动态规划解法 令\(dp[i][j][k]\)代表当前选至位置\(i\)处于第\(j\)段当前是否选取 ...

  4. P2389 电脑班的裁员

    题意:长度为n的序列,选出k个连续的字段,使和最大(有负数) 暴力只选正数且不考虑k的边界问题50(数据...) 正解从$O(n^3)到O(n)$不等,($O(n)$不会) DP 1.$O(n^3)$ ...

  5. 【Luogu】P2389电脑班的裁员(DP)

    题目链接 sbt交了三遍才过是我的耻辱…… 就是设f[i][j]搞个三重循环DP一下,以上. #include<cstdio> #include<cstdlib> #inclu ...

  6. Linux下安装性能测试负载机LG

    系统:CentOS release 6.6 (Final)  x86_64 安装包: 1.LRLG_00031.iso [Load Generator Standalone (Linux 64-bit ...

  7. bootstrap 之 xs,sm,md,lg && 主要颜色

    mobile – xs ( <768px ) tablet – sm ( 768~991px ) desktop – md ( 992~1170px ) large desktop – lg ( ...

  8. boostrap中lg,md,sm,xs

    boostrap中lg,md,sm,xs分别表示多少px? .col-xs- 超小屏幕 手机 (<768px).col-sm- 小屏幕 平板 (≥768px).col-md- 中等屏幕 桌面显示 ...

  9. LG 2.2.1 P350安卓系统刷机,问题总结,希望对需要的朋友有助

    手机误删软件导致短信,键盘等无声音提醒 我的手机前几天被我误删了一个软件,导致电话接不了,别人打电话的时候,老提示我在通话中,但是我可以在通话中看到对方的打电话记录.短信,键盘,USB连接,等等都没有 ...

随机推荐

  1. C#图解教程(第四版)—02—类的基本概念

    类  是一种能 存储数据  并且  执行代码  的数据结构,他包含数据成员和函数成员 .成员可以是9种可能的成员类型的任意组合 字段 属性 方法 常量 构造函数 析构函数 运算符 索引器 事件 1 字 ...

  2. golang bool值

    目录 前言 1.基本介绍 2.类型转换 3.使用: 跳转 前言 不做文字的搬运工,多做灵感性记录 这是平时学习总结的地方,用做知识库 平时看到其他文章的相关知识,也会增加到这里 随着学习深入,会进行知 ...

  3. gtk.Builder.AddFromFile SIGSEGV.

    可能是由于GTK没有初始化的缘故,在程序开头加上gtk.Init(nil)进行初始化 或者参考我这篇博客就不会出错了

  4. JavaFX桌面应用-视频转码工具(支持爱奇艺qsv转mp4)

    最近由于需要将在爱奇艺下载的视频(qsv)转化了mp4,用JavaFX开发一个视频转码工具,算是JavaFX开发的第一个应用吧. 支持qsv转码mp4,理论上支持各种格式,仅测试了flv,qsv格式. ...

  5. python字典的增删改查

    字典dict 知识点: {}括起来,以键值对形式存储的容器性数据类型: 键-必须是不可变数据类型,且是唯一的: -值可以是任意数据类型.对象. 优点:关联性强,查询速度快. 缺点:以空间换时间. 字典 ...

  6. JavaScript设计模式之策略模式【组合委托】

    前言:语言只是工具,思想才是核心 今天要总结的是 策略模式 策略在开发中的应用非常广泛,所以也是非常常见且使用的设计模式. 在实际开发中,往往在实现一个功能时,有多种解决方案可行. 常见场景: 解压: ...

  7. 第5章 JDBC/ODBC服务器

    第5章 JDBC/ODBC服务器 Spark SQL也提供JDBC连接支持,这对于让商业智能(BI)工具连接到Spark集群上以 及在多用户间共享一个集群的场景都非常有用.JDBC 服务器作为一个独立 ...

  8. cinder 卷迁移进度的代码分析

    一.cinder-api服务的入口函数 D:\code-program\cinder-ocata_cinder\cinder\api\contrib\admin_actions.py from cin ...

  9. 团队作业5:Alpha版本测试和发布(歪瑞古德小队)

    目录 一.项目文档和代码 二.Alpha版本测试报告 2.1 功能测试 2.1.1 功能列表 2.1.2 场景测试 2.1.3 测试结果 2.1.4 bug清单 2.2 兼容性测试 2.3 性能测试 ...

  10. ISO8601

    日期和时间的组合表示法 合并表示时,要在时间前面加一大写字母T,如要表示东八区时间2004年5月3日下午5点30分8秒,可以写成2004-05-03T17:30:08+08:00或20040503T1 ...