【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]一类堆+链表+贪心问题
今天我们来介绍一系列比较经典的堆+链表问题.这类问题的特点是用堆选取最优解,并且通过一些加减操作来实现"反悔". 在看题之前,我们先来介绍一个神器:手写堆. 手写堆的一大好处就是可 ...
随机推荐
- 《梦断代码Dreaming In Code》阅读笔记(一)
第0章!干得漂亮! 这是我看到这本书冒出来的第一个想法.身为计算机系的学生,对于从0开始的任何事情,都感到格外亲切. 进入阅读之后,疑惑.惊讶.感叹渐渐取代了之前轻松的心情,原来做软件竟是攀越一座又一 ...
- Ubuntu录制gif动态图
大神写博客的时候通常一个Demo会附带一个动态图展示效果.在windows和mac上应该很容易找到录制工具,下面记录一下我在ubuntu下录制gif的过程. 下载byzanz录制工具 在ubuntu软 ...
- Java中ArrayList与数组间相互转换
在实际的 Java 开发中,如何选择数据结构是一个非常重要的问题. 衡量标准化(读的效率与改的效率) : ① Array: 读快改慢 ② Linked :改快读慢 ③ Hash:介于两者之间 实现Li ...
- matlab的二维卷积操作(转)
MATLAB的conv2函数实现步骤(conv2(A,B)): 其中,矩阵A和B的尺寸分别为ma*na即mb*nb ① 对矩阵A补零,第一行之前和最后一行之后都补mb-1行,第一列之前和最后一列之后都 ...
- tomcat web页面管理应用配置
大部分时候,我们的tomcat服务器都不是部署在本机,那么怎么样不通过ftp/sftp方式来将war包部署到tomcat容器呢? tomcat有提供web页面管理应用的功能. 我们来看看怎么配置实现该 ...
- c#对xml的操作
操作xml可以通过XElement对象,比较方便的使用列举以下几点: 把字符串转变成XElement,保存成xml文件,加载xml文件: //把字符串解析成XElement对象 string str ...
- VBA 练习-从两个库中调用数据到活动表中
练习VBA Sub 填报入库单() Dim basedb As String, cpdb As String, wb As Workbook, ws As Worksheet, curWs As Wo ...
- [转]matlab中squeeze函数的用法,numel的用法
squeeze的作用是移除单一维. 如果矩阵哪一个维数是1,B=squeeze(A)就将这个维数移除. 考虑2-by-1-by-3 数组Y = rand(2,1,3). 这个数组有单一维 —就是每页仅 ...
- cf 443 D. Teams Formation](细节模拟题)
cf 443 D. Teams Formation(细节模拟题) 题意: 给出一个长为\(n\)的序列,重复\(m\)次形成一个新的序列,动态消除所有k个连续相同的数字,问最后会剩下多少个数(题目保证 ...
- bzoj2733: [HNOI2012]永无乡(splay+启发式合并/线段树合并)
这题之前写过线段树合并,今天复习Splay的时候想起这题,打算写一次Splay+启发式合并. 好爽!!! 写了长长的代码(其实也不长),只凭着下午的一点记忆(没背板子...),调了好久好久,过了样例, ...