【题目链接】

https://www.lydsy.com/JudgeOnline/problem.php?id=2288

【算法】

先将这个序列的正负数合并起来,变成一个正负交替的序列

如果新序列的正数个数小于等于M,那么直接输出正数的和即可

否则,我们可以将某些正数和负数合并起来,或者不要某些正数

将所有数按绝对值排序,放入堆中,问题就转化为了 : 在这些数中选出(Cnt - M)个数(其中Cnt为正数的个数),

选了一个数后相邻的两个数就不能选,使得最后的和尽可能小

这个问题可以用CTSC2007数据备份的方法来解决,详见 : https://www.cnblogs.com/evenbao/p/9252503.html

【代码】

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + ;
const int INF = 2e9; struct info
{
int d,pos;
}; int i,n,m,l,r,cnt,ans,len;
int a[MAXN],b[MAXN],val[MAXN],pre[MAXN],nxt[MAXN];
bool visited[MAXN];
info tmp; class Heap
{
private :
int tot;
info hp[MAXN];
public :
inline bool cmp(info a,info b)
{
return a.d < b.d;
}
inline void Up(int x)
{
if (x == ) return;
int fa = x >> ;
if (cmp(hp[x],hp[fa]))
{
swap(hp[x],hp[fa]);
Up(fa);
}
}
inline void Down(int x)
{
int son = x << ;
if (son > tot) return;
if ((son + <= tot) && cmp(hp[son+],hp[son])) son++;
if (cmp(hp[son],hp[x]))
{
swap(hp[son],hp[x]);
Down(son);
}
}
inline void insert(info x)
{
tot++;
hp[tot] = x;
Up(tot);
}
inline void del()
{
swap(hp[],hp[tot]);
tot--;
Down();
}
inline info get()
{
return hp[];
}
} H; int main()
{ scanf("%d%d",&n,&m);
for (i = ; i <= n; i++) scanf("%d",&a[i]);
while (n && a[n] <= ) n--;
i = ;
while (i <= n && a[i] <= ) i++;
if (i > n)
{
printf("%d\n",);
return ;
}
for (; i <= n; i++)
{
if ((a[i] > && a[i-] > ) || (a[i] <= && a[i-] <= )) b[len] += a[i];
else b[++len] = a[i];
}
for (i = ; i <= len; i++)
{
if (b[i] > )
{
ans += b[i];
cnt++;
} else b[i] = -b[i];
}
if (cnt <= m)
{
printf("%d\n",ans);
return ;
}
for (i = ; i <= len; i++)
{
pre[i] = i - ;
nxt[i] = i + ;
H.insert((info){b[i],i});
}
b[] = b[len+] = INF;
for (i = m; i < cnt; i++)
{
tmp = H.get();
while (visited[tmp.pos])
{
H.del();
tmp = H.get();
}
ans -= tmp.d;
H.del();
visited[pre[tmp.pos]] = true;
visited[nxt[tmp.pos]] = true;
b[tmp.pos] = b[pre[tmp.pos]] + b[nxt[tmp.pos]] - tmp.d;
nxt[pre[pre[tmp.pos]]] = tmp.pos;
pre[tmp.pos] = pre[pre[tmp.pos]];
pre[nxt[nxt[tmp.pos]]] = tmp.pos;
nxt[tmp.pos] = nxt[nxt[tmp.pos]];
H.insert((info){b[tmp.pos],tmp.pos});
}
printf("%d\n",ans); return ; }

【BZOJ 2288】 生日礼物的更多相关文章

  1. Bzoj 2288 生日礼物题解

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  9. [BZOJ 1293] 生日礼物

    Link: BZOJ 1293 传送门 Solution: 这题直接上尺取法就行了吧 先将每种颜色第一个放入优先队列,用$mx$维护当前的末尾位置 每次取出第一个颜色,更新答案.将其下一个放入队列中去 ...

随机推荐

  1. php用户注册常用检测、写入

    // 判断数据库是否已经存在 $check_sql = "select * from user where idNumber='$idNumber'"; $check_query ...

  2. CAD向控件注册一个命令(com接口VB语言)

    主要用到函数说明: MxDrawXCustomFunction::Mx_RegistUserCustomCommand 向控件注册一个命令,用户在命令行输入命令名这个字符串,就会触发执行命令事件 命令 ...

  3. IDEA 创建一个普通的java项目

    IntelliJ IDEA 如何创建一个普通的java项目,及创建java文件并运行 首先,确保idea软件正确安装完成,java开发工具包jdk安装完成. IntelliJ IDEA下载地址:htt ...

  4. 破解js中的this指向

    首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象(这句话有些问题,后面会解释为什么会有问题,虽然 ...

  5. PAT 1034. Head of a Gang

    1034. Head of a Gang (30) One way that the police finds the head of a gang is to check people's phon ...

  6. 【Codeforces 340D】Bubble Sort Graph

    [链接] 我是链接,点我呀:) [题意] 让你根据冒泡排序的规则 建立一张图 问你这张图的最大独立子集的大小 [题解] 考虑a[i]会和哪些点连边? 必然是在a[i]左边且比它大的数字以及在a[i]右 ...

  7. Java基础学习总结(70)——开发Java项目常用的工具汇总

    要想全面了解java开发工具,我们首先需要先了解一下java程序的开发过程,通过这个过程我们能够了解到java开发都需要用到那些工具. 首先我们先了解完整项目开发过程,如图所示: 从上图中我们能看到一 ...

  8. noip模拟赛 fateice-shop

    题目背景 紫女,韩国歌舞坊(实为刺客组织)紫兰轩之主,千娇百媚,美艳无方.武艺高强且极有谋略胆识,精通奇石药物,冶炼之术及制毒用毒之术独步天下,真实姓名与来历无人知晓,只因总是身着一袭紫衣,所以众人以 ...

  9. hdu 4888 最大流给出行列和求矩阵

    第一步,考虑如何求是否有解.使用网络流求解,每一行和每一列分别对应一个点,加上源点和汇点一共有N+M+2个点.有三类边: 1. 源点 -> 每一行对应的点,流量限制为该行的和 2. 每一行对应的 ...

  10. hdu 4941 stl的map<node,int>用法

    #include<iostream> #include<cstdio> #include<cstring> #include<map> using na ...