首页 技术 正文
技术 2022年11月6日
0 收藏 991 点赞 316 浏览 1790 个字

【POJ Challenge】生日礼物

题目大意:给定一个长度为$n$的序列,允许选择不超过$m$个连续的部分,求元素之和的最大值。

数据范围:$1\le n, m\le 10^5$。


题解

显然的一步转化,就是把连续的、同符号的元素求和变成一个。

这样就变成了一串正负号交替的序列。

现在把所有正数都加一起,如果满足条件就直接输出。

不满足的话,我们发现:

我们可以选取一个负数,这样可以合并左右两个正数。

我们也可以删掉一个正数。

以上两个操作,都会使我们的选取的个数$-\ -$。

至于到底应该怎么选呢?

就弄一个堆,每次拿出来代价最小的操作就好。

代码

#include <bits/stdc++.h>#define N 100010 using namespace std;int a[N], b[N], nxt[N], pre[N];bool vis[N];char *p1, *p2, buf[100000];#define nc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1 ++ )int rd() {
int x = 0, f = 1;
char c = nc();
while (c < 48) {
if (c == '-')
f = -1;
c = nc();
}
while (c > 47) {
x = (((x << 2) + x) << 1) + (c ^ 48), c = nc();
}
return x * f;
}struct Node {
int val, id;
friend bool operator < (const Node &a, const Node &b) {
return a.val > b.val;
}
};priority_queue<Node> q;int main() {
int n = rd(), m = rd();
for (int i = 1; i <= n; i ++ ) {
b[i] = rd();
}
int n1 = 1;
a[1] = b[1];
for (int i = 2; i <= n; i ++ ) {
if ((a[n1] <= 0 && b[i] <= 0) || (a[n1] >= 0 && b[i] >= 0)) a[n1] += b[i];
else a[ ++ n1] = b[i];
}
if (a[n1] <= 0) {
n1 -- ;
}
if (a[1] <= 0) {
for (int i = 1; i < n1; i ++ ) {
a[i] = a[i + 1];
}
n1 -- ;
}
n = n1;
int ans = 0, sum = 0;
for (int i = 1; i <= n; i ++ ) {
if (a[i] > 0) {
sum ++ ;
ans += a[i];
}
Node mdl;
mdl.val = abs(a[i]);
mdl.id = i;
q.push(mdl);
nxt[i] = i + 1;
pre[i] = i - 1;
a[i] = abs(a[i]);
}
// cout << ans << endl ;
// cout << sum << endl ;
nxt[n] = pre[1] = 0;
if (sum <= m) {
cout << ans << endl ;
return 0;
}
m = sum - m;
for (int i = 1; i <= m; i ++ ) {
Node mdl = q.top();
q.pop();
while (vis[mdl.id] && !q.empty()) {
mdl = q.top();
q.pop();
}
// cout << mdl.val << endl ;
if (vis[mdl.id])
break;
ans -= mdl.val;
if (q.empty())
break;
int tmp = mdl.id;
if (!pre[tmp]) {
vis[tmp] = true;
vis[nxt[tmp]] = true;
pre[nxt[nxt[tmp]]] = 0;
}
else if(!nxt[tmp]) {
vis[tmp] = true;
vis[pre[tmp]] = true;
nxt[pre[pre[tmp]]] = 0;
}
else {
vis[nxt[tmp]] = true;
vis[pre[tmp]] = true;
mdl.val = a[tmp] = a[nxt[tmp]] + a[pre[tmp]] - a[tmp];
if (nxt[nxt[tmp]])
pre[nxt[nxt[tmp]]] = tmp;
if (pre[pre[tmp]])
nxt[pre[pre[tmp]]] = tmp;
pre[tmp] = pre[pre[tmp]];
nxt[tmp] = nxt[nxt[tmp]];
q.push(mdl);
}
}
cout << ans << endl ;
return 0;
}

小结:这玩意儿好像叫模拟费用流吧,不会不会有空学/cy

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,487
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,903
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,736
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,486
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:8,126
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:5,287