【题目链接】

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. JS——null

    变量被赋值为null,目的往往是为了销毁这个对象: var n1 = 1; n1 = null;

  2. 三角形状的点阵模糊效果iOS源码

    源码FFAngularPointilism,FFAngularPointilism能够将UIImageView像添加滤波器一样生成三角形状的点阵模糊效果.可以通过动画方式来模糊,也可以立刻模糊.另外并 ...

  3. Linux监控实时log

    https://jingyan.baidu.com/article/93f9803f5545a3e0e46f5596.html

  4. PHP操作Redis相关函数

    String数据类型 $redis->set('key','TK'); $redis->set('number','1'); //设置值 $redis->setex('key',5, ...

  5. win10 ubuntu18双系统环境搭建

    感谢前辈辛勤总结,根据这3篇文章成功配置了双系统 https://blog.csdn.net/qq_24624539/article/details/81775635 https://blog.csd ...

  6. maxtrid 3D视差

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. Light Oj - 1134 Be Efficient

    题目传送门:Be Efficient 题意:输入n和m,然后输入有n个元素的一个序列,问有多少个子序列元素的和能整除m. 思路:求前缀和,利用一个前缀的一个定理求解. 前缀和的一个定理是:每次求的前缀 ...

  8. 机器学习中jupyter lab的安装方法以及使用的命令

    安装JupyterLab使用pip安装: pip install jupyterlab# 必须将用户级目录添加 到环境变量才能启动pip install --userbinPATHjupyter la ...

  9. 《Java JDK 8 学习笔记》序

    摘录自<Java JDK 8 学习笔记> 翻开一本书,无非是想从书中得到知识,只是为何你要得到书中的知识,才是我想知道的答案,而这个答案决定了你在取得知识的过程中是否快乐! 多数人在取得知 ...

  10. everyday two problems / 3.1

    T1.string 题意: 给定由小写字母组成的长度为 n 的字符串 将其所有 n * (n + 1) / 2 个子串按字典序排序 输出第 k 个子串 k > (n * (n + 1) / 2) ...