2288: 【POJ Challenge】生日礼物

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 856  Solved: 260
[Submit][Status][Discuss]

Description

ftiasch 18岁生日的时候,lqp18_31给她看了一个神奇的序列 A1A2, ..., AN. 她被允许选择不超过 M 个连续的部分作为自己的生日礼物。

自然地,ftiasch想要知道选择元素之和的最大值。你能帮助她吗?

 

Input

第1行,两个整数 N (1 ≤ N ≤ 105) 和 M (0 ≤ M ≤ 105), 序列的长度和可以选择的部分。

第2行, N 个整数 A1A2, ..., AN (0 ≤ |Ai| ≤ 104), 序列。

Output

一个整数,最大的和。

Sample Input

5 2
2 -3 2 -1 2

Sample Output

5

HINT

Source

  这道题当时第一眼以为连续的m个数,然后以为是二分加上单调队列,还好又读了一遍,发现是m个区间,这就比较有意思了。

  首先,我们可以先把所有符号相同的区间合在一起,来简化一下问题,然后这道题就变成了在一个正数与负数相间的数列中找出m个数使他们的和最大,但是我们要注意一点,这些数其实还可以合并成一个数,所以我们不能拿贪心去做。所以我们可以把答案分为两种情况,第一,所有正数的个数小于等于m那么我们可以直接输出了,第二正数的个数大于m,那么我们就有又有两种选择了,舍去某个正数或通过一个负数将两个区间合并在一起。对于位于首尾两个位置的负数我们可以的知他们并无法连接两个正数,换言之,选他们并不能减少当前所选的区间,所以我们在一开始就应当把他们刨去。同时我们也可以发现如果我们选了一个负数那么两侧的正数是不能再被选择丢掉的,而整个序列又是正负相间的,所以我们就可以将这个问题转化为在当前数列中选取若干个不相邻的数数是他们的和最小。然后,这道题就是Bzoj1150数据备份了。

  

 #include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<cmath>
#include<map>
#include<vector>
#define N 100005
using namespace std;
int n,m,a[N],zz;
struct no
{
long long sum;
int mid;
bool friend operator > (no a,no b)
{
return a.sum>b.sum;
}
}node[N];
int pre[N],fro[N];
bool fw[N];
priority_queue<no,vector<no>,greater<no > > q1;
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
scanf("%d",&a[i]);
long long sm=,ans=,js=,la=;
for(int i=;i<=n;i++)
{
if(a[i]==)continue;
if(a[i]*la<)
{
zz++;
node[zz].sum=sm;
if(sm>)
{
js++;
ans+=sm;
}
sm=;
if(zz==&&la<)zz=;
}
la=a[i];
sm+=a[i];
}
if(sm>)
{
js++,ans+=sm;
zz++;
node[zz].sum=sm;
}
if(js<=m)
{
printf("%lld\n",ans);
exit();
}
m=js-m;
for(int i=;i<=zz;i++)
{
node[i].mid=i;
node[i].sum=abs(node[i].sum);
q1.push(node[i]);
pre[i]=i-,fro[i]=i+;
}
fro[zz]=;
node[].sum=0x7fffffff;
while(m--)
{
while(fw[q1.top().mid]) q1.pop();
no tt=q1.top();q1.pop();
int x=tt.mid;
ans-=tt.sum;
tt.sum=-tt.sum;
tt.sum+=node[pre[x]].sum+node[fro[x]].sum;
node[x].sum=tt.sum; fw[pre[x]]=fw[fro[x]]=;
pre[x]=pre[pre[x]];
fro[x]=fro[fro[x]];
pre[fro[x]]=x;
fro[pre[x]]=x;
q1.push(tt);
}
printf("%lld\n",ans);
return ;
}

Bzoj 2288 生日礼物题解的更多相关文章

  1. BZOJ 1179 Atm 题解

    BZOJ 1179 Atm 题解 SPFA Algorithm Tarjan Algorithm Description Input 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来 ...

  2. BZOJ 2288 【POJ Challenge】生日礼物(贪心+优先队列)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2288 [题目大意] 给出一列数,求最多取m段连续的数字,使得总和最大 [题解] 首先我 ...

  3. 【链表】BZOJ 2288: 【POJ Challenge】生日礼物

    2288: [POJ Challenge]生日礼物 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 382  Solved: 111[Submit][S ...

  4. bzoj 2288 【POJ Challenge】生日礼物 双向链表+堆优化

    2288: [POJ Challenge]生日礼物 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1003  Solved: 317[Submit][ ...

  5. 【BZOJ 2288】 2288: 【POJ Challenge】生日礼物 (贪心+优先队列+双向链表)

    2288: [POJ Challenge]生日礼物 Description ftiasch 18岁生日的时候,lqp18_31给她看了一个神奇的序列 A1, A2, ..., AN. 她被允许选择不超 ...

  6. 【BZOJ 2288】 生日礼物

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=2288 [算法] 先将这个序列的正负数合并起来,变成一个正负交替的序列 如果新序列的正 ...

  7. BZOJ 2288: 【POJ Challenge】生日礼物 堆&&链表

    就是堆+链表,十分像 数据备份 对吧? 把相邻的正数和相邻的负数合并成一整个正数块和负数块,最后只剩一些交替相间的正块与负块了吧? 显然,正块的个数<=m时,全部选走就获得了最大权值,否则我们可 ...

  8. bzoj 2288: 【POJ Challenge】生日礼物【链表+堆】

    参考:http://blog.csdn.net/w_yqts/article/details/76037315 把相同符号的连续数字加起来,合并后ans先贪心的加上所有正数,如果正数个数sum> ...

  9. BZOJ 2288: 【POJ Challenge】生日礼物 贪心 + 堆 + 链表

    好像是模拟费用流 Code: #include <bits/stdc++.h> #define setIO(s) freopen(s".in","r" ...

随机推荐

  1. LINQ查询表达式---------let子句

    LINQ查询表达式---------let子句 let子句创建一个范围变量来存储结果,变量被创建后,不能修改或把其他表达式的结果重新赋值给它.此范围变量可以再后续的LINQ子句中使用. class P ...

  2. 发布ActiveX控件

    最近我们正在研究ActiveX技术.我们使用Delphi 5创建了一个具有ActiveForm的ActiveX控件应用程序.这个控件产生一个.OCX文件.现在,我们需要把这个控件部署在服务器端,在用户 ...

  3. 零元学Expression Blend 4 &ndash; Chapter 43 如何指定Childwindow PopUp位置

    原文:零元学Expression Blend 4 – Chapter 43 如何指定Childwindow PopUp位置 有网友询问我有关Childwindow是否能指定弹出位置? 其实只要透过小小 ...

  4. WPF使用Font-Awesome字体

    官方网站:https://fontawesome.com/ 使用教程: 学习WPF——使用Font-Awesome图标字体 - liulun - 博客园https://www.cnblogs.com/ ...

  5. Android零基础入门第31节:几乎不用但要了解的AbsoluteLayout绝对布局

    原文:Android零基础入门第31节:几乎不用但要了解的AbsoluteLayout绝对布局 前面几期基本学习了Android开发中常用的四种布局,之所以把AbsoluteLayout放在后面来学习 ...

  6. Android零基础入门第36节:Android系统事件的响应

    原文:Android零基础入门第36节:Android系统事件的响应 在开发Android应用时,有时候可能需要让应用程序随系统设置而进行调整,比如判断系统的屏幕方向.判断系统方向的方向导航设备等.除 ...

  7. 改善C#程序的建议7:正确停止线程

    原文:改善C#程序的建议7:正确停止线程 开发者总尝试对自己的代码有更多的控制.“让那个还在工作的线程马上停止下来”就是诸多要求中的一种.然而事与愿违,这里面至少存在两个问题: 第一个问题是:正如线程 ...

  8. Linux下的wfopen(手工打造)

    Of Linux on wfopen (open wide-character version of the file name and mode) to achieve Not directly a ...

  9. Qt在Windows下的三种编程环境搭建(图文并茂,非常清楚)good

    尊重作者,支持原创,如需转载,请附上原地址:http://blog.csdn.net/libaineu2004/article/details/17363165 从QT官网可以得知其支持的平台.编译器 ...

  10. 深入了解Windows句柄到底是什么(句柄是逻辑指针,或者是指向结构体的指针,图文并茂,非常清楚)good

    总是有新入门的Windows程序员问我Windows的句柄到底是什么,我说你把它看做一种类似指针的标识就行了,但是显然这一答案不能让他们满意,然后我说去问问度娘吧,他们说不行网上的说法太多还难以理解. ...