【BZOJ2288】生日礼物 [贪心]
生日礼物
Time Limit: 10 Sec Memory Limit: 128 MB
[Submit][Status][Discuss]
Description
ftiasch 18岁生日的时候,lqp18_31给她看了一个神奇的序列 A1, A2, ..., AN. 她被允许选择不超过 M 个连续的部分作为自己的生日礼物。
自然地,ftiasch想要知道选择元素之和的最大值。你能帮助她吗?
Input
第1行,两个整数 N 和 M , 序列的长度和可以选择的部分。
第2行, N 个整数 A1, A2, ..., AN , 序列。
Output
一个整数,最大的和。
Sample Input
2 -3 2 -1 2
Sample Output
HINT
1 ≤ N ≤ 105, 0 ≤ M ≤ 105, 0 ≤ |Ai| ≤ 104
Solution
首先,我们可以把权值正负相同的连续的一段合并起来。Ans+=(所有正数),块数++。
然后把每一段的绝对值加入到小根堆里面。每次贪心取出最小的来,块数减去 1 直到满足题目要求为止。
为什么这样可以对呢?我们来讨论一下:
1. 如果删去的段是正数, 那么相当于不取这个。
2. 如果删去的段是负数,那么相当于取了这个段合并它左右的两个段。
但是!这样会有一个问题!就是无法考虑连续取5个段及以上的情况,并且无法保证:取了一个数不取相连的两个数(会导致块数不减)。
所以判断一下,每次取段的时候,删去左右两个小段,加上一个大段(他们三个合并的值)即可。
Code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<queue>
using namespace std;
typedef long long s64; const int ONE = ;
const int INF = ; int n, m;
int a[ONE], A[ONE];
int pre[ONE], suc[ONE];
int Ans, block; struct power
{
int id, val;
bool operator <(power a) const
{
return a.val < val;
}
};
priority_queue <power> q; int get()
{
int res=,Q=;char c;
while( (c=getchar())< || c> )
if(c=='-')Q=-;
res=c-;
while( (c=getchar())>= && c<= )
res=res*+c-;
return res*Q;
} int main()
{
n = get(); m = get();
for(int i = ; i <= n; i++) a[i] = get();
int from = ; while(a[from] <= ) from++;
int to = n; while(a[to] <= ) to--; n = ;
for(;from <= to;)
{
if( (a[from-] <= && a[from] <= ) || (a[from-] > && a[from] > ))
A[n] += a[from];
else A[++n] = a[from];
from++;
} for(int i = ; i <= n; i++)
{
pre[i] = i - ;
suc[i] = i + ;
if(A[i] > ) Ans += A[i], block++;
A[i] = abs(A[i]);
q.push( (power){i, A[i]} );
} if(block <= m) {printf("%d", Ans); return ;} pre[] = suc[n] = ; for(;;)
{
for(;;)
{
power u = q.top();
if(u.val != A[u.id]) q.pop();
else break;
} power u = q.top(); q.pop();
Ans -= u.val; if(pre[u.id] == ) A[suc[u.id]] = INF, pre[suc[u.id]] = ;
else
if(suc[u.id] == ) A[pre[u.id]] = INF, suc[pre[u.id]] = ;
else
{
A[u.id] = A[pre[u.id]] + A[suc[u.id]] - A[u.id];
A[pre[u.id]] = A[suc[u.id]] = INF;
pre[u.id] = pre[pre[u.id]];
suc[u.id] = suc[suc[u.id]];
pre[suc[u.id]] = suc[pre[u.id]] = u.id;
q.push( (power){u.id, A[u.id]} );
} block--; if(block <= m) break;
} printf("%d", Ans);
}
【BZOJ2288】生日礼物 [贪心]的更多相关文章
- 2018.09.30 bzoj2288:生日礼物(贪心+线段树)
传送门 线段树经典题目. 每次先找到最大子段和来更新答案,然后利用网络流反悔退流的思想把这个最大字段乘-1之后放回去. 代码: #include<bits/stdc++.h> #defin ...
- bzoj2288 生日礼物 (线段树)
我当然想选最大的子段和啦 但要选M次 那不一定就是最好的 所以提供一个反悔的选项,我选了一段以后,就把它们乘个-1,然后再选最好的(类似于网络流的思路) 这个可以用线段树来维护,记一个区间包含左端点/ ...
- BZOJ2288 生日礼物
本题是数据备份的进阶版. 首先去掉所有0,把连续的正数/负数连起来. 计算所有正数段的个数与总和. 然后考虑数据备份,有一点区别: 如果我们在数列中选出一个负数,相当于把它左右连起来. 选出一个正数, ...
- P2564 [SCOI2009]生日礼物 贪心
https://www.luogu.org/problemnew/show/P2564) 题意 有n个珠子,包括k中颜色,找出长度最小的一个区间,使得这个区间中包含所有的颜色. 思路 把n个珠子按照位 ...
- BZOJ 2288: 【POJ Challenge】生日礼物 贪心 + 堆 + 链表
好像是模拟费用流 Code: #include <bits/stdc++.h> #define setIO(s) freopen(s".in","r" ...
- 我的刷题单(8/37)(dalao珂来享受切题的快感
P2324 [SCOI2005]骑士精神 CF724B Batch Sort CF460C Present CF482A Diverse Permutation CF425A Sereja and S ...
- [bzoj2288][pojChallenge]生日礼物【贪心+堆+链表】
题目描述 ftiasch 18岁生日的时候,lqp18_31给她看了一个神奇的序列 A1, A2, -, AN. 她被允许选择不超过 M 个连续的部分作为自己的生日礼物. 自然地,ftiasch想要知 ...
- [bzoj2288]【POJ Challenge】生日礼物_贪心_堆
[POJ Challenge]生日礼物 题目大意:给定一个长度为$n$的序列,允许选择不超过$m$个连续的部分,求元素之和的最大值. 数据范围:$1\le n, m\le 10^5$. 题解: 显然的 ...
- [BZOJ2288&BZOJ1150]一类堆+链表+贪心问题
今天我们来介绍一系列比较经典的堆+链表问题.这类问题的特点是用堆选取最优解,并且通过一些加减操作来实现"反悔". 在看题之前,我们先来介绍一个神器:手写堆. 手写堆的一大好处就是可 ...
随机推荐
- sql update limit1
更新限制:为了避免全表更新,错误更新影响太多,加上limit1 多了一层保障.
- 哈希表 STL map
计数排序时我们使用一个数组来记录出现的数字的次数,而当数据范围太大时,无法建立一个那么大地数组(而且可能空间利用率很低,太浪费),此时可以改用hash table . binary search tr ...
- Java常用类之File类
File 类: 1. java.io.File 类代表系统文件名(路径名.文件名); 2. File 类常见的构造方法: 2.1. File(String pathname):通过将给定路径名字符串转 ...
- iOS- Exception异常处理
1.Exception 前言 在iOS里对异常的处理及捕获,并没有其它语言里那么常见,相信很多iOS程序员都知道,更多的时候是对内存的的检测与分析,检测相关内存方面的问题. 而在app闪退并不是因为内 ...
- 安装配置erlang_db_driver
erlang-db-driver是北京融易通公司开源的一个erlang支持众多数据库的一个驱动类库,据其wiki介绍,其支持MySQL, Oracle, Sybase, DB2 and Informi ...
- JSP传递数组给JS的方法
由于JSP页面的数组无法直接传到JS.所以采用以下方法来获取数组. <% String[] title = { "姓名 ", "学号 ", "性 ...
- 3dContactPointAnnotationTool开发日志(一)
周日毕设开题报告结束后浪了一天,今天又要开始回归正轨了.毕设要做一个人和物体的接触点标注工具,听上去好像没啥难度,其实实现起来还是挺麻烦的. 今天没做啥,就弄了个3d场景做样例.把界面搭了一下 ...
- cacti 添加mysql 监控 (远程服务器)
监控主机 192.168.24.69 ,以下用A表示 被监控主机 192.168.24.79,以下用B标识 记得在A服务器的cacti中导入监控mysql的templates文件 1.在B上安 ...
- ResultSet 可滚动性和可更新性
JDBC 2.0 API 为结果集增加了两个新的基本能力:可滚动性和可更新性,我想肯定满足了你的要求.在滚动结果集中可用的方法有: rs.previous();//向前滚动 rs.next();//向 ...
- matlab怎么选取excel的特定列构成数组
例如: