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. js中的scrollTop、offsetTop、clientTop

    scrollHeight:获取对象可滚动的高度. scrollWidth:获取对象可滚动的宽度. scrollTop:获取对象最顶端与对象可见区域最顶端的距离. scrollLeft:获取对象左边界与 ...

  2. Android零基础入门第77节:Activity任务栈和启动模式

    通过前面的学习,Activity的基本使用都已掌握,接下来一起来学习更高级的一些内容. Android采用任务栈(Task)的方式来管理Activity的实例.当启动一个应用时,Android就会为之 ...

  3. Android零基础入门第76节:Activity数据保存和横竖屏切换

    在前面几期学习了Activity的创建.配置.启动和停止,还学了Activity的生命周期,本期一起来学习Activity有关的更多事儿. 一.数据保存 通过上一期 LogCat 窗口打印的日志可以看 ...

  4. SQL Server 将某一列的值拼接成字符串

    名称 海鲜水产 水果蔬菜 海参 肉禽蛋 牛排 腊味 生鲜食品 将以上一列变成: 生鲜食品,海鲜水产,水果蔬菜,海参,牛排,肉禽蛋,腊味 sql for xml path('')

  5. How to Capture the Integer-Divide-By-Zero Error in C++(提前定义信号)

    How to Capture the Integer-Divide-By-Zero Error in C++? MANUAL CAPTURE The simple and straightforwar ...

  6. qt开发的小软件,可以递归转换文件编码(qt为了防止内存泄露所做的保护机制)

    应用场景 当你下载别人的源码的时候,而别人的源码跟你自己电脑里面的编码不一致的情况下将会出现乱码,但是如果要一个个转换编码的话那么那样所需要花的时间太多,所以就有必要写一个软件递归遍历项目下面所有的文 ...

  7. Js 动态插入css js文件

    function loadjscssfile(filename,filetype){ var file, //动态插入的文件 doc = document; if(filetype == " ...

  8. 一线Python运维开发带你秒懂Flask框架

    相信曾经纠结过这个问题:怎样才能彻底掌握flask? Flask是一个使用 Python 编写的轻量级 Web 应用框架.其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2 . ...

  9. Tido 习题-二叉树-区间查询

    题目描述 食堂有N个打饭窗口,现在正到了午饭时间,每个窗口都排了很多的学生,而且每个窗口排队的人数在不断的变化.现在问你第i个窗口到第j个窗口一共有多少人在排队? 输入 输入的第一行是一个整数T,表示 ...

  10. WebGL场景的两种地面构造方法

    总述:大部分3D编程都涉及到地面元素,在场景中我们使用地面作为其他物体的承载基础,同时也用地面限制场景使用者的移动范围,还可以在通过设置地块的属性为场景的不同位置设置对应的计算规则.本文在WebGL平 ...