本题是数据备份的进阶版。

首先去掉所有0,把连续的正数/负数连起来。

计算所有正数段的个数与总和。

然后考虑数据备份,有一点区别:

如果我们在数列中选出一个负数,相当于把它左右连起来。

选出一个正数,相当于抛弃它。

总和加上那个负数/减去那个正数即为变化。

所以把val按照绝对值进堆,出来,减去绝对值即可。

注意:两边的负数不能选,因为旁边没有东西去给你连。

实际操作的时候我存了负数,在比较函数里加abs

 #include <cstdio>
#include <queue>
#include <cmath>
const int N = ; struct Sta {
int p, val;
Sta(int pq, int v) {
p = pq;
val = v;
}
};
inline int abs(const int &x) {
return x > ? x : -x;
}
inline bool operator <(const Sta &x, const Sta &y) {
return abs(x.val) > abs(y.val);
}
struct ListNode {
int pre, nex, val;
bool use;
}li[N << ]; int top, head, tail; int a[N], ans, cnt;
std::priority_queue<Sta> Q; inline void init() {
head = (N << ) - ;
tail = head - ;
li[head].nex = tail;
li[tail].pre = head;
return;
} inline void add(int x) {
top++;
int p = li[tail].pre;
li[top].pre = p;
li[top].nex = tail;
li[p].nex = top;
li[tail].pre = top;
li[top].val = x;
Q.push(Sta(top, x));
if(x > ) {
ans += x;
cnt++;
}
return;
} inline int get() {
Sta t = Q.top();
Q.pop();
while(!Q.empty() && (li[t.p].use || li[t.p].val != t.val)) {
t = Q.top();
Q.pop();
}
int x = t.p; if(li[x].val < && li[x].pre == head) {
li[x].use = ;
li[li[x].nex].pre = head;
li[head].nex = li[x].nex;
return get();
}
if(li[x].val < && li[x].nex == tail) {
li[x].use = ;
li[tail].pre = li[x].pre;
li[li[x].pre].nex = tail;
return get();
} if(li[x].nex == tail && li[x].pre == head) {
li[x].use = ;
return li[x].val;
}
if(li[x].nex == tail) {
int ans = li[x].val;
li[x].val += li[li[x].pre].val;
li[li[x].pre].use = ;
li[x].pre = li[li[x].pre].pre;
li[li[x].pre].nex = x;
Q.push(Sta(x, li[x].val));
return ans;
}
if(li[x].pre == head) {
int ans = li[x].val;
li[x].val += li[li[x].nex].val;
li[li[x].nex].use = ;
li[x].nex = li[li[x].nex].nex;
li[li[x].nex].pre = x;
Q.push(Sta(x, li[x].val));
return ans;
}
int ans = li[x].val;
li[x].val += li[li[x].nex].val;
li[x].val += li[li[x].pre].val;
li[li[x].pre].use = ;
li[li[x].nex].use = ;
li[x].pre = li[li[x].pre].pre;
li[x].nex = li[li[x].nex].nex;
li[li[x].pre].nex = x;
li[li[x].nex].pre = x;
Q.push(Sta(x, li[x].val));
return ans;
} int main() {
int m, n;
init();
scanf("%d%d", &n, &m);
for(int i = ; i <= n; i++) {
scanf("%d", &a[i]);
}
int t = ;
bool f = ;
for(int i = ; i <= n; i++) {
if(!a[i]) {
continue;
}
if(f) {
if(a[i] < ) {
continue;
}
else {
f = ;
}
}
if(1ll * a[i] * t >= ) {
t += a[i];
}
else {
add(t);
t = a[i];
}
}
if(t > ) {
add(t);
} for(int i = m + ; i <= cnt; i++) {
ans -= abs(get());
}
printf("%d", ans);
return ;
}

AC代码

BZOJ2288 生日礼物的更多相关文章

  1. bzoj2288 生日礼物 (线段树)

    我当然想选最大的子段和啦 但要选M次 那不一定就是最好的 所以提供一个反悔的选项,我选了一段以后,就把它们乘个-1,然后再选最好的(类似于网络流的思路) 这个可以用线段树来维护,记一个区间包含左端点/ ...

  2. 2018.09.30 bzoj2288:生日礼物(贪心+线段树)

    传送门 线段树经典题目. 每次先找到最大子段和来更新答案,然后利用网络流反悔退流的思想把这个最大字段乘-1之后放回去. 代码: #include<bits/stdc++.h> #defin ...

  3. 我的刷题单(8/37)(dalao珂来享受切题的快感

    P2324 [SCOI2005]骑士精神 CF724B Batch Sort CF460C Present CF482A Diverse Permutation CF425A Sereja and S ...

  4. bzoj2288【POJ Challenge】生日礼物*

    bzoj2288[POJ Challenge]生日礼物 题意: 给一个序列,求不超过m个连续的部分,使元素和最大.序列大小≤100000 题解: 先把连续的正数和负数合并起来,接着如果正数个数小于m则 ...

  5. BZOJ2288: 【POJ Challenge】生日礼物

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

  6. [bzoj2288][pojChallenge]生日礼物【贪心+堆+链表】

    题目描述 ftiasch 18岁生日的时候,lqp18_31给她看了一个神奇的序列 A1, A2, -, AN. 她被允许选择不超过 M 个连续的部分作为自己的生日礼物. 自然地,ftiasch想要知 ...

  7. BZOJ2288:[POJ Challenge]生日礼物——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=2288 ftiasch 18岁生日的时候,lqp18_31给她看了一个神奇的序列 A1, A2, . ...

  8. 【BZOJ2288】生日礼物 [贪心]

    生日礼物 Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description ftiasch 18岁生日的时候, ...

  9. BZOJ2288 【POJ Challenge】生日礼物 【堆 + 链表】

    题目 ftiasch 18岁生日的时候,lqp18_31给她看了一个神奇的序列 A1, A2, ..., AN. 她被允许选择不超过 M 个连续的部分作为自己的生日礼物. 自然地,ftiasch想要知 ...

随机推荐

  1. springboot 如何操作redis

    1.首先应该引入 依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactI ...

  2. hive条件过滤

    where 过滤 %代表任意个字符,_代表一个字符; \\ 转移字符.\\_代表下划线

  3. php 将数组转换网址URL参数

    $array =array ( 'id' =123, 'name' = 'dopost' );echo http_build_query( $array );//得到结果id=123name=dopo ...

  4. Sqoop 使用详解(内含对官方文档的解析)

    Sqoop 是 Cloudera 公司创造的一个数据同步工具,现在已经完全开源了. 目前已经是 hadoop 生态环境中数据迁移的首选,另外还有 ali 开发的 DataX 属于同类型工具,由于社区的 ...

  5. python数学第六天【指数族】

  6. hdu1878-并查集,欧拉回路

    纯裸题..写着方便理解... 题意:判断一个无向图是否存在欧拉回路... 解题思路:并查集判断一下是否联通,然后再判断一下点的度数是否为偶数就行了: #include<iostream> ...

  7. java基础1之基本数据类型

    java的数据类型 整数型(byte.short.int.long) 编程过程中,默认是int类型.long类型的字面值后面需要加上L或l PS:java底层,byte.short是按照32位计算的. ...

  8. java 转义字符"\u0010" "\010" "\2"等

    java转义字符 \xxx                八进制转义符 \uxxxx          十六进制转义符 像"\010","\u0010"这种字符 ...

  9. fpm 打包工具安装调试

    https://github.com/jordansissel/fpm  官方git yum install ruby-devel gcc make rpm-build rubygems gem so ...

  10. JDK 与TOMCAT的安装详解

    转自:http://www.jb51.net/article/51909.htm Tomcat7.0.22在Windows下详细配置过程 一.JDK1.7安装 1.下载jdk,下载地址:http:// ...