hdu1024 Max Sum Plus Plus的另一种解法
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1024
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1053
【题解】
原来的解法:http://www.cnblogs.com/galaxies/p/hdu1024.html
原来的解法思路是正着,我们加数,现在考虑删数
我们先特判几种情况(可以全选正,全选正还不够)
现在只剩下一种情况,段数<正数段数
我们可以把数字合并变成+/-/+/-...这个情况
那我们考虑的是合并。
每次我们选出+的段,意为舍弃这一段
选出-的段,意为把这一段和旁边两个正段合并
所以选出代表要把这段绝对值从答案里减去,我们希望越小越好,所以维护一个小根堆(或set)
那么合并的时候把选出的段和旁边两段直接相加即可,由于这个绝对值是最小的,所以加起来还是旁边两段的符号。
特别注意如果在边界上出现了负数那么这个负数是没有任何用的,因为我们选他不能合并来使段数减小,所以直接删掉即可。
在进队列的时候如果边界上出现了0,那么一样把它删掉,因为选0一定是出现这种情况
10000 -10000 -10000 ....
然后你选了第一个,变成了0 -10000 ...
很明显我们第一次选了10000,意为舍弃它,并合并,所以和周围合并变成了0,再选0,没有任何意义,不能使段数减小,反而增加。
至于为什么不能在取top的时候判,因为会有这种情况
m=1,n=4,a[]={0,-1,-1,0}
原本是0,就已经合法,是有实际意义的,所以不能判掉。
然后就过了
# include <set>
# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h> using namespace std; typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 1e6 + ;
const int mod = 1e9+; # define RG register
# define ST static ll a[M], ans = ;
int m, n;
int p[M], pn;
int tot1, tot2;
set< pair<ll, int> > s; inline int sgn(int x) {return x<?:;}
inline ll myabs(ll x) {return x>?x:-x;} inline void transform() {
n = ;
ll t = p[]; int s = sgn(t);
for (int i=; i<=pn; ++i) {
if(sgn(p[i]) == s)
t += p[i];
else {
a[++n] = t;
t = p[i];
s = sgn(t);
}
}
a[++n] = t;
// for (int i=1; i<=n; ++i) printf("%d ", a[i]);
} int Minus[M];
inline void solve_minus() {
int tn = , tem = m-tot1;
for (int i=; i<=pn; ++i) if(p[i] < ) Minus[++tn] = p[i];
sort(Minus+, Minus+tn+);
while(tem--) ans += Minus[tn--];
} int L[M], R[M]; inline void del(int x) {
L[R[x]] = L[x];
R[L[x]] = R[x];
} inline void solve() {
s.clear();
int T = tot2 - m;
for (int i=; i<=n+; ++i) L[i] = R[i] = ;
for (int i=; i<n; ++i) L[i] = i-, R[i] = i+;
L[n] = n-;
for (int i=; i<=n; ++i) s.insert(make_pair(myabs(a[i]), i));
// cout << T << endl;
while(T--) {
pair<ll, int> top = *s.begin();
s.erase(top);
int x = top.second, y;
if(a[x] < && (!L[x] || !R[x])) {
del(x);
++T;
continue;
}
ll sum = a[x];
ans -= myabs(sum);
if(L[x]) {
y = L[x];
sum += a[y];
s.erase(make_pair(myabs(a[y]), y));
del(L[x]);
}
if(R[x]) {
y = R[x];
sum += a[y];
s.erase(make_pair(myabs(a[y]), y));
del(R[x]);
}
a[x] = sum;
if(sum == ) del(x);
else s.insert(make_pair(myabs(a[x]), x));
}
} int main() {
while(cin >> m >> pn) {
tot1 = tot2 = ;
for (int i=; i<=pn; ++i) scanf("%d", p+i);
transform();
for (int i=; i<=pn; ++i) tot1 += (p[i] >= );
for (int i=; i<=n; ++i) tot2 += (a[i] >= );
ans = ;
for (int i=; i<=n; ++i)
if(a[i] >= ) ans += a[i];
// for (int i=1; i<=n; ++i) cout << a[i] << ' ';
// cout << endl;
// cout << "ans = " << ans << endl;
if(tot2 <= m && m <= tot1) cout << ans << endl;
else if(m > tot1) {
solve_minus();
cout << ans << endl;
} else {
solve();
cout << ans << endl;
}
}
return ;
}
hdu1024 Max Sum Plus Plus的另一种解法的更多相关文章
- HDU1024 Max Sum Plus Plus 【DP】
Max Sum Plus Plus Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others ...
- hdu1024 Max Sum Plus Plus[降维优化好题(貌似以后可以不用单调队列了)]
Max Sum Plus Plus Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others ...
- hdu1024 Max Sum Plus Plus 滚动dp
Max Sum Plus Plus Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others ...
- HDU1024 Max Sum Plus Plus —— DP + 滚动数组
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1024 Max Sum Plus Plus Time Limit: 2000/1000 MS ...
- HDU1024 Max Sum Plus Plus (优化线性dp)
Now I think you have got an AC in Ignatius.L's "Max Sum" problem. To be a brave ACMer, we ...
- HDU-1024 Max Sum Plus Plus 动态规划 滚动数组和转移优化
题目链接:https://cn.vjudge.net/problem/HDU-1024 题意 给n, m和一个序列,找m个不重叠子串,使这几个子串内元素和的和最大. n<=1e6 例:1 3 1 ...
- hdu1024 Max Sum Plus Plus
动态规划,给定长度为n(≤1e6)的整数数组和整数m,选取m个连续且两两无交集的子区间,求所有方案中使得区间和最大的最大值. dp[i][j]表示结束位置(最后一个区间最后一个元素的位置)为i且选取区 ...
- HDU1024 Max Sum Plus Plus(DP)
状态:d(i,j)它代表前j划分数i部并且包括第一j最佳结果时的数.g(i,j)表示前j划分数i最好的结果时,段,g(m,n)结果,需要. 本题数据较大.需採用滚动数组.注意:这题int类型就够用了, ...
- HDU1024 Max Sum Plus Plus(dp)
链接:http://acm.hdu.edu.cn/showproblem.php?pid=1024 #include<iostream> #include<vector> #i ...
随机推荐
- python__高级 : GC垃圾回收相关
python的垃圾回收机制是以引用计数为主,加上标记-清除,分代收集等辅助方式组成的,如果想打开gc功能,需要 import gc 模块 ,然后 gc.enable() 就打开了这个功能,关闭是 gc ...
- POJ:2456-Aggressive cows
Aggressive cows Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 18313 Accepted: 8716 Desc ...
- 6 Django的视图层
视图函数 一个视图函数,简称视图,是一个简单的Python 函数,它接受Web请求并且返回Web响应.响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片. . ...
- 找出Xcode没有使用的图片
#! /bin/sh PROJ=`find . -name '*.xib' -o -name '*.[mh]'` for png in ` find . -name '*.png'` do name ...
- 《Cracking the Coding Interview》——第8章:面向对象设计——题目9
2014-04-23 23:57 题目:如何设计一个内存文件系统,如果可以的话,附上一些代码示例. 解法:很遗憾,对我来说不可以.完全没有相关经验,所以实在无从入手.这题目应该和工作经验相关吧? 代码 ...
- Percona-Tookit工具包之pt-duplicate-key-checker
Preface I suppose that we have a requirement of checking out how many duplicated indexes on ...
- 自动化测试(二)如何用python写一个用户登陆功能
需求信息: 写一个判断登录的程序: 输入: username password 最大错误次数是3次,输入3次都没有登录成功,提示错误次数达到上限 需要判断输入是否为空,什么也不输入,输入一个空格.n个 ...
- python 之发送邮件服务[原著] 海瑞博客
Python 发送邮件 使用默认的django的发送邮件,只适用于单邮箱. 作者:海瑞博客 http://www.hairuinet.com/ setting中配置 # send e-mail EMA ...
- 求:斐波那契数列的第n项
def he (n): if n < 3 : return 1 return he(n-1)+he(n-2)print(he(n))
- 孤荷凌寒自学python第四十九天继续研究跨不同类型数据库的通用数据表操作函数
孤荷凌寒自学python第四十九天继续研究跨不同类型数据库的通用数据表操作函数 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 今天继续建构自感觉用起来顺手些的自定义模块和类的代码. 不同类型 ...