【POJ Challenge】生日礼物

题目大意:给定一个长度为$n$的序列,允许选择不超过$m$个连续的部分,求元素之和的最大值。

数据范围:$1\le n, m\le 10^5$。


题解

显然的一步转化,就是把连续的、同符号的元素求和变成一个。

这样就变成了一串正负号交替的序列。

现在把所有正数都加一起,如果满足条件就直接输出。

不满足的话,我们发现:

我们可以选取一个负数,这样可以合并左右两个正数。

我们也可以删掉一个正数。

以上两个操作,都会使我们的选取的个数$-\ -$。

至于到底应该怎么选呢?

就弄一个堆,每次拿出来代价最小的操作就好。

代码

#include <bits/stdc++.h>

#define N 100010 

using namespace std;

int a[N], b[N], nxt[N], pre[N];

bool vis[N];

char *p1, *p2, buf[100000];

#define nc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1 ++ )

int rd() {
int x = 0, f = 1;
char c = nc();
while (c < 48) {
if (c == '-')
f = -1;
c = nc();
}
while (c > 47) {
x = (((x << 2) + x) << 1) + (c ^ 48), c = nc();
}
return x * f;
} struct Node {
int val, id;
friend bool operator < (const Node &a, const Node &b) {
return a.val > b.val;
}
}; priority_queue<Node> q; int main() {
int n = rd(), m = rd();
for (int i = 1; i <= n; i ++ ) {
b[i] = rd();
}
int n1 = 1;
a[1] = b[1];
for (int i = 2; i <= n; i ++ ) {
if ((a[n1] <= 0 && b[i] <= 0) || (a[n1] >= 0 && b[i] >= 0)) a[n1] += b[i];
else a[ ++ n1] = b[i];
}
if (a[n1] <= 0) {
n1 -- ;
}
if (a[1] <= 0) {
for (int i = 1; i < n1; i ++ ) {
a[i] = a[i + 1];
}
n1 -- ;
}
n = n1;
int ans = 0, sum = 0;
for (int i = 1; i <= n; i ++ ) {
if (a[i] > 0) {
sum ++ ;
ans += a[i];
}
Node mdl;
mdl.val = abs(a[i]);
mdl.id = i;
q.push(mdl);
nxt[i] = i + 1;
pre[i] = i - 1;
a[i] = abs(a[i]);
}
// cout << ans << endl ;
// cout << sum << endl ;
nxt[n] = pre[1] = 0;
if (sum <= m) {
cout << ans << endl ;
return 0;
}
m = sum - m;
for (int i = 1; i <= m; i ++ ) {
Node mdl = q.top();
q.pop();
while (vis[mdl.id] && !q.empty()) {
mdl = q.top();
q.pop();
}
// cout << mdl.val << endl ;
if (vis[mdl.id])
break;
ans -= mdl.val;
if (q.empty())
break;
int tmp = mdl.id;
if (!pre[tmp]) {
vis[tmp] = true;
vis[nxt[tmp]] = true;
pre[nxt[nxt[tmp]]] = 0;
}
else if(!nxt[tmp]) {
vis[tmp] = true;
vis[pre[tmp]] = true;
nxt[pre[pre[tmp]]] = 0;
}
else {
vis[nxt[tmp]] = true;
vis[pre[tmp]] = true;
mdl.val = a[tmp] = a[nxt[tmp]] + a[pre[tmp]] - a[tmp];
if (nxt[nxt[tmp]])
pre[nxt[nxt[tmp]]] = tmp;
if (pre[pre[tmp]])
nxt[pre[pre[tmp]]] = tmp;
pre[tmp] = pre[pre[tmp]];
nxt[tmp] = nxt[nxt[tmp]];
q.push(mdl);
}
}
cout << ans << endl ;
return 0;
}

小结:这玩意儿好像叫模拟费用流吧,不会不会有空学/cy

[bzoj2288]【POJ Challenge】生日礼物_贪心_堆的更多相关文章

  1. BZOJ3502PA2012Tanie linie&BZOJ2288[POJ Challenge]生日礼物——模拟费用流+链表+堆

    题目描述 n个数字,求不相交的总和最大的最多k个连续子序列. 1<= k<= N<= 1000000. 输入 输出 样例输入 5 2 7 -3 4 -9 5 样例输出 13   根据 ...

  2. [bzoj2288][POJ Challenge]生日礼物

    用堆维护双向链表来贪心... 数据范围显然不容许O(nm)的傻逼dp>_<..而且dp光是状态就n*m个了..显然没法优化 大概就会想到贪心乱搞了吧...一开始想贪心地通过几段小的负数把正 ...

  3. [bzoj2287][poj Challenge]消失之物_背包dp_容斥原理

    消失之物 bzoj-2287 Poj Challenge 题目大意:给定$n$个物品,第$i$个物品的权值为$W_i$.记$Count(x,i)$为第$i$个物品不允许使用的情况下拿到重量为$x$的方 ...

  4. BZOJ2288:[POJ Challenge]生日礼物——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=2288 ftiasch 18岁生日的时候,lqp18_31给她看了一个神奇的序列 A1, A2, . ...

  5. BZOJ2288:[POJ Challenge]生日礼物

    浅谈堆:https://www.cnblogs.com/AKMer/p/10284629.html 题目传送门:https://lydsy.com/JudgeOnline/problem.php?id ...

  6. [bzoj4345][POI2016]Korale_堆_贪心_线段树_dfs

    bzoj4345 POI2016 Korale 题目链接:https://lydsy.com/JudgeOnline/problem.php?id=4345 数据范围:略. 题解: 由于$k$的范围问 ...

  7. poj 3253 Fence Repair 贪心 最小堆 题解《挑战程序设计竞赛》

    地址 http://poj.org/problem?id=3253 题解 本题是<挑战程序设计>一书的例题 根据树中描述 所有切割的代价 可以形成一颗二叉树 而最后的代价总和是与子节点和深 ...

  8. [bzoj2097][Usaco2010 Dec]Exercise 奶牛健美操_贪心_树形dp_二分

    Exercise bzoj-2097 Usaco-2010 Dec 题目大意:题目链接 注释:略. 想法:题目描述生怕你不知道这题在考二分. 关键是怎么验证?我们想到贪心的删边. 这样的策略是显然正确 ...

  9. [bzoj4027][HEOI2015]兔子与樱花_贪心_树形dp

    兔子与樱花 bzoj-4027 HEOI-2015 题目大意:每个点有c[i]朵樱花,有一个称重m, son[i]+c[i]<=m.如果删除一个节点,这个节点的樱花或移动到它的祖先中深度最大的, ...

随机推荐

  1. CentOS7部署tomcat

    首先检查是否安装了jdk,然后再查看是否配置了JAVA_HOME 配置JAVA_HOME的方法: 我的是jdk已经安装好了是1.8 我需要找到它的安装目录 [root@bogon xwg]# java ...

  2. Django-批量更新

    1.表结构 class Student(models.Model): """ 学生表(已报名) """ customer = models. ...

  3. 利用ceph-deploy部署ceph存储集群

    一.环境准备 创建两台主机,ip地址和主机名如下 192.168.2.100,主机名ceph-1 192.168.2.101,主机名ceph-2 每个主机 新增加一块数据盘,分区根据自己需要分区即可, ...

  4. 8.8 JQuery框架

    8.8 JQuery框架 一.JQuery是一个javascript的框架,是对javascript的一种封装. 通过JQuery可以非常方便的操作html的元素\要使用Jquery需要导入一个第三方 ...

  5. 预处理、const、static与sizeof-内联函数与宏有什么区别

    1:二者的区别如下: (1)内联函数在编译时展开,宏在预编译时展开. (2)在编译的时候,内联函数可以直接被镶嵌到目标代码中,而宏只是一个简单的文本替换. (3)内联函数可以完成诸如类型检测.语句是否 ...

  6. flutter常用内置动画组件

    文章目录 AnimatedContainer AnimatedCrossFade Hero AnimatedBuilder DecoratedBoxTransition FadeTransition ...

  7. rsync+inotify 实时双向同步

    前言 在遇到需要 nginx 负载均衡,承受较高并发的情况,同时会有双机相同目录内容须保持一致的需求 rsync+inotify 是一个不错的解决方案,相较于 rsync+sersync 在处理大量文 ...

  8. react 闲谈 之 JSX

    jsx元素-> React.createElement -> 虚拟dom对象 -> render方法 1.在react中想将js当作变了引入到jsx中需要使用{} 2.在jsx中,相 ...

  9. 解决 无法启动此程序,因为计算机中丢失opencv_world341.dll。请尝试重新安装改程序已解决此问题

    在运行OpenCV程序时报错:“无法启动此程序,因为计算机中丢失opencv_world341.dll.请尝试重新安装改程序已解决此问题”. 解决方法 我的bin目录是 D:\opencv\build ...

  10. Centos7 安装.Net Core SDK

    1.在安装.NET之前,您需要注册Microsoft密钥,注册产品存储库并安装所需的依赖项.这只需要每台机器完成一次. sudo rpm -Uvh https://packages.microsoft ...