BZOJ2288: 【POJ Challenge】生日礼物
2288: 【POJ Challenge】生日礼物
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 284 Solved: 82
[Submit][Status]
Description
ftiasch 18岁生日的时候,lqp18_31给她看了一个神奇的序列 A1, A2, ..., AN. 她被允许选择不超过 M 个连续的部分作为自己的生日礼物。
自然地,ftiasch想要知道选择元素之和的最大值。你能帮助她吗?

Input
第1行,两个整数 N (1 ≤ N ≤ 105) 和 M (0 ≤ M ≤ 105), 序列的长度和可以选择的部分。
第2行, N 个整数 A1, A2, ..., AN (0 ≤ |Ai| ≤ 104), 序列。
Output
一个整数,最大的和。
Sample Input
2 -3 2 -1 2
Sample Output
HINT
Source
题解:
感觉和数据备份这题有点像,但是又转化不过来。。。看了hzwer的题解之后恍然大悟了。。。
首先连在一块的正负相同的肯定可以看成一个点,然后我们就得到了一个正负交替的数列,并且首位两项都是正数(负数去掉)
然后如果正的项数<=m,那显然我们全部选走就获得了最大权值,否则我们需要做一点牺牲。
1)不选某些正项
2)选一些负项使得相邻的正项成为1块
记所有正数之和为sum,我们需要进行上面两种操作使得sum减掉的数最小并且满足只有m块。
我们把所有数的绝对值放入一个堆,每次取最小元素x。sum'-=x
那么如果该数原来是正的,意思是不选它;
如果是负的,意思是把它两边的正数合并。
但直接这样做是不行的,我们必须保证取负的时候两边的正的必须不被取,取正的时候两边的负的不被取。
换句话说,不能选择相邻的两个数!我们成功的将此题转化成了数据备份问题。
orz!
代码:
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<string>
#define inf 1000000000
#define maxn 100000+5
#define maxm 500+100
#define eps 1e-10
#define ll long long
#define pa pair<int,int>
#define for0(i,n) for(int i=0;i<=(n);i++)
#define for1(i,n) for(int i=1;i<=(n);i++)
#define for2(i,x,y) for(int i=(x);i<=(y);i++)
#define for3(i,x,y) for(int i=(x);i>=(y);i--)
#define mod 1000000007
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=*x+ch-'';ch=getchar();}
return x*f;
}
int n,k,s,t,ans,a[maxn],b[maxn],l[maxn],r[maxn];
priority_queue<pa,vector<pa>,greater<pa> >q;
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
t=read();k=read();
for1(i,t)a[i]=read();while(a[t]<=)t--;
s=;while(a[s]<=)s++;
for(;s<=t;s++)if((a[s]>&&a[s-]>)||(a[s]<=&&a[s-]<=))b[n]+=a[s];else b[++n]=a[s];
for1(i,n)if(b[i]>){ans+=b[i];k--;}else b[i]=-b[i];
if(k>=){cout<<ans<<endl;return ;}
for1(i,n)l[i]=i-,r[i]=i+,q.push(pa(b[i],i));
r[n]=;
for1(i,abs(k))
{
while(b[q.top().second]!=q.top().first)q.pop();
int x=q.top().second;q.pop();
ans-=b[x];
if(!l[x]){b[r[x]]=inf;l[r[x]]=;}
else if(!r[x]){b[l[x]]=inf;r[l[x]]=;}
else
{
b[x]=b[l[x]]+b[r[x]]-b[x];
b[l[x]]=b[r[x]]=inf;
r[l[x]=l[l[x]]]=l[r[x]=r[r[x]]]=x;
q.push(pa(b[x],x));
}
}
cout<<ans<<endl;
return ;
}
还有一点,之所以赋删去的点的权值为inf是为了不用手打堆,erase233
BZOJ2288: 【POJ Challenge】生日礼物的更多相关文章
- [bzoj2288][POJ Challenge]生日礼物
用堆维护双向链表来贪心... 数据范围显然不容许O(nm)的傻逼dp>_<..而且dp光是状态就n*m个了..显然没法优化 大概就会想到贪心乱搞了吧...一开始想贪心地通过几段小的负数把正 ...
- BZOJ3502PA2012Tanie linie&BZOJ2288[POJ Challenge]生日礼物——模拟费用流+链表+堆
题目描述 n个数字,求不相交的总和最大的最多k个连续子序列. 1<= k<= N<= 1000000. 输入 输出 样例输入 5 2 7 -3 4 -9 5 样例输出 13 根据 ...
- BZOJ2288:[POJ Challenge]生日礼物——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=2288 ftiasch 18岁生日的时候,lqp18_31给她看了一个神奇的序列 A1, A2, . ...
- BZOJ2288:[POJ Challenge]生日礼物
浅谈堆:https://www.cnblogs.com/AKMer/p/10284629.html 题目传送门:https://lydsy.com/JudgeOnline/problem.php?id ...
- bzoj2288【POJ Challenge】生日礼物*
bzoj2288[POJ Challenge]生日礼物 题意: 给一个序列,求不超过m个连续的部分,使元素和最大.序列大小≤100000 题解: 先把连续的正数和负数合并起来,接着如果正数个数小于m则 ...
- [bzoj2288]【POJ Challenge】生日礼物_贪心_堆
[POJ Challenge]生日礼物 题目大意:给定一个长度为$n$的序列,允许选择不超过$m$个连续的部分,求元素之和的最大值. 数据范围:$1\le n, m\le 10^5$. 题解: 显然的 ...
- 2288.【POJ Challenge】生日礼物 链表+堆+贪心
BZOJ2288 [POJ Challenge]生日礼物 题意: 给一个长度为\(n\)的数组,最多可以选\(m\)个连续段,问选取的最大值是多少 题解: 先把连续的符号相同的值合并,头和尾的负数去掉 ...
- 【链表】BZOJ 2288: 【POJ Challenge】生日礼物
2288: [POJ Challenge]生日礼物 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 382 Solved: 111[Submit][S ...
- bzoj 2288 【POJ Challenge】生日礼物 双向链表+堆优化
2288: [POJ Challenge]生日礼物 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1003 Solved: 317[Submit][ ...
随机推荐
- Canvas实现曲线运动
前言 Html5添加的最受欢迎的功能就是<canvas>元素,它负责在页面中设定一个区域,然后在里面可以通过javascript动态地在其内绘制图形. 主流浏览器,IE9+,手机端都是支持 ...
- STORM 免费且开源的WebSerivce测试工具
一.名称 STORM 是一款免费且开源的WebSerivce测试工具 二.使用方式 1.发布自己的webservice服务 例如:http://www.webxml.com.cn/WebService ...
- C语言之指针1.1数组
void main() { ]={,,,,,}; ;i++) { printf("%d\n",*(arr+i)); } } 输出结果时候123456
- c#中的重写方法与隐藏方
1.父类中有方法a,添加virtua修饰符可声明为虚方法,在子类中可以用override声明后重写方法a. 2.父类中有方法a,在子类中可以有new修饰符声明后隐藏父类方法. 子类重写方法后,对于子类 ...
- 反射 介绍System.Type类
本节先介绍system.Type类,通过这个类可以访问关于任何数据类型的信息. 1. system.Type类以前把Type看作一个类,但它实际上是一个抽象的基类.只要实例化了一个Type对象,实际上 ...
- 使用GitHub For Windows托管Visual Studio项目
本文写得比较早,更新的在VS上使用GitHub的文章请移步:Visual Stuido 2015 Community 使用 GitHub 插件 因为最近同时再看很多技术方面的书,书上的例子有很多自己想 ...
- 配置php连接apache
配置php连接apache 1.安装php所需要的库 yum install zlib-devel libxml2-devel libjpeg-devel libjpeg-turbo-devel li ...
- Linux的关机与重启命令
Linux的关机与重启命令 作者: Aillo, 发布于2009-05-10, 在系统分类下, 1条留言. 重启命令:1.reboot2.shutdown -r now 立刻重启(root用户使用)3 ...
- linux磁盘以及文件系统
df 查看磁盘总容量 -i 显示inodes号 -h 使用合适的单位显示磁盘大小 -m 以M为单位显示 -k 以K为单位显示 默认K显示 du 用来查看某个目录或者文件所占空间大小 参数:-abckm ...
- hadoop1中hdfs原理详解
HDFS是Hadoop Distribute File System的简称,也是Hadoop的一个分布四文件系统 一.HDFS的主要设计理念 1.存储超大文件 这里的 “超大文件” 是指几百MB .G ...