[日常训练]最大M子段和
Description
在长度为的序列
中选出
段互不相交的子段,求最大字段和.
Input
第一行两个整数.
第二行个整数
.
Output
一行一个整数表示最大值.
Sample Input
10 -1 10 -1 10
Sample Output
29
HINT
Solution
如果序列中正整数个数,直接取最大的
个数的和即可.
将序列合并成若干个交错的正负段和,如-1,-2,3,4,-5,-6可以合并成-1-2,3+4,-5-6.
记录所有正数段之和,设正数段个数为
,则需要把k段正数段合并成
段.
对于每一段正数段有两种操作:
1.舍弃;
2.与相邻串合并.
可以用堆来实现:将所有段的绝对值扔入堆中,每次取最小的元素(如果在当前序列中是左或右没有元素的负数段就跳过),
,将
与在当前序列中的左右元素合并即可.
#include<cmath>
#include<ctime>
#include<stack>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 100005
#define M -100000000000001LL
using namespace std;
typedef long long ll;
struct heap{
ll k;int n;
}h[N],tmp;
ll a[N],num[N],sum,ans;
int lst[N],nxt[N],n,m,cnt;
inline bool cmp(ll x,ll y){
return x>y;
}
inline bool chk(heap x,heap y){
if(x.k!=y.k) return x.k<y.k;
return x.n<y.n;
}
inline void swim(int i){
heap a=h[i];int j=i>>1;
while(j&&chk(a,h[j])){
h[i]=h[j];num[h[i].n]=i;i=j;j>>=1;
}
h[i]=a;num[h[i].n]=i;
}
inline void sink(int i){
heap a=h[i];int j=i<<1;
while(j<=cnt){
if(j<cnt&&chk(h[j+1],h[j])) ++j;
if(chk(a,h[j])) break;
h[i]=h[j];num[h[i].n]=i;i=j;j<<=1;
}
h[i]=a;num[h[i].n]=i;
}
inline void del(int u){
if(!u||u>n) return;
if(num[u]){
if(num[u]==cnt) --cnt;
else{
h[num[u]]=h[cnt--];sink(num[u]);swim(num[u]);
}
}
lst[nxt[u]]=lst[u];nxt[lst[u]]=nxt[u];
}
inline void init(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i){
scanf("%lld",&a[i]);
if(a[i]>=0LL){
++cnt;ans+=a[i];
}
}
/*正数个数<=m*/
if(cnt<=m){
sort(a+1,a+1+n,cmp);
for(int i=1;i<=m;++i)
sum+=a[i];
printf("%lld\n",sum);
return;
}
cnt=0;
for(int i=1;i<=n;++i){
if(sum*a[i]<0LL){
a[++cnt]=sum;sum=a[i];
}
else sum+=a[i];
}
a[++cnt]=sum;
n=cnt;cnt=0;
for(int i=1;i<=n;++i)
if(a[i]>0) ++cnt;
/*正数区间数<=m*/
if(cnt<=m){
printf("%lld\n",ans);return;
}
for(int i=1;i<=n;++i){
lst[i]=i-1;nxt[i]=i+1;
}
lst[n+1]=n;nxt[0]=1;
m=cnt-m;cnt=0;
for(int i=1;i<=n;++i){
h[++cnt].k=abs(a[i]);h[cnt].n=i;num[i]=cnt;swim(cnt);
}
while(m){
tmp=h[1];h[1]=h[cnt--];sink(1);
if(((!lst[tmp.n]||nxt[tmp.n]>n)&&a[tmp.n]<0)||!a[tmp.n]) continue;
ans-=tmp.k;a[tmp.n]+=a[lst[tmp.n]]+a[nxt[tmp.n]];
del(lst[tmp.n]);del(nxt[tmp.n]);
h[++cnt].k=abs(a[tmp.n]);h[cnt].n=tmp.n;swim(cnt);
--m;
}
printf("%lld\n",ans);
}
int main(){
freopen("sequence.in","r",stdin);
freopen("sequence.out","w",stdout);
init();
fclose(stdin);
fclose(stdout);
return 0;
}
[日常训练]最大M子段和的更多相关文章
- 「日常训练」ZgukistringZ(Codeforces Round #307 Div. 2 B)
题意与分析(CodeForces 551B) 这他妈哪里是日常训练,这是日常弟中弟. 题意是这样的,给出一个字符串A,再给出两个字符串B,C,求A中任意量字符交换后(不限制次数)能够得到的使B,C作为 ...
- 「日常训练」 Fire!(UVA-11624)
与其说是训练不如说是重温.重新写了Java版本的代码. import java.util.*; import java.math.*; import java.io.BufferedInputStre ...
- 「知识学习&日常训练」莫队算法(一)(Codeforce Round #340 Div.2 E)
题意 (CodeForces 617E) 已知一个长度为\(n\)的整数数列\(a[1],a[2],-,a[n]\),给定查询参数\(l,r\),问\([l,r]\)内,有多少连续子段满足异或和等于\ ...
- 「日常训练」COMMON 约数研究(HYSBZ-1968)
题意与分析 感谢https://www.cnblogs.com/Leohh/p/7512960.html的题解.这题话说原来不在我的训练范围,正好有个同学问我,我就拿来做做.数学果然不是我擅长的啊,这 ...
- 「日常训练」 Mike and Fun (CFR305D2B)
题意(CodeForces 548B) 每次对01矩阵中的一位取反,问每次操作后,单列中最长连续1的长度. 分析 非常非常简单,但是我当时训练的时候WA了四次...无力吐槽了,人间 不值得.jpg 代 ...
- 「日常训练」Common Subexpression Elimination(UVa-12219)
今天做的题目就是抱佛脚2333 懂的都懂. 这条题目干了好几天,最后还是参考别人的代码敲出来了,但是自己独立思考了两天多,还是有收获的. 思路分析 做这条题我是先按照之前的那条题目(The SetSt ...
- 集训队日常训练20181117 DIV2
大佬们一顿操作猛如虎,拼命AC强啊 4262: 区间异或 Time Limit(Common/Java):1000MS/3000MS Memory Limit:65536KByteTotal ...
- [日常训练]string
Description 给定一个长度为$n$的字符串,串中的字符保证是前$k$个小写字母.你可以在字符串后再添加$m$个字符,使得新字符串所包含的不同的子序列数量尽量多.当然,前提是只能添加前$k$个 ...
- [日常训练]yayamao的神题
Description $yayamao$是数学神犇,一天他在纸上计算起了$1/P$, 我们知道按照模拟除法可以得到准确解,例如$1/7=0.(142857),1/10=0.1(0)$.$yayama ...
随机推荐
- removeNode is not defined removeNode is not a function
在javascript操作dom树的时候可能会经常遇到增加,删除节点的事情,比如一个输入框后一个增加按钮,一个删除按钮,点击增加就增加 个输入框,点击删除就删除对应的输入框.在一些js框架,如Prot ...
- How To Create an IE-Only Stylesheet
https://css-tricks.com/how-to-create-an-ie-only-stylesheet/ https://css-tricks.com/snippets/css/css- ...
- 利用ThinkPHP自带的七牛云驱动上传文件到七牛云以及删除七牛云文件方法
一.准备工作 1.注册七牛云账号 2.选择对象储存->创建空间->设置为公开 3.在config配置文件中添加以下代码 'UPLOAD_FILE_QINIU' => array ( ...
- mac OS X Yosemite 上编译hadoop 2.6.0/2.7.0及TEZ 0.5.2/0.7.0 注意事项
1.jdk 1.7问题 hadoop 2.7.0必须要求jdk 1.7.0,而oracle官网已经声明,jdk 1.7 以后不准备再提供更新了,所以趁现在还能下载,赶紧去down一个mac版吧 htt ...
- stack overflow错误分析
stack overflow(堆栈溢出)就是不顾堆栈中分配的局部数据块大小,向该数据块写入了过多的数据,导致数据越界,结果覆盖了老的堆栈数据. 或者解释为 在长字符串中嵌入一段代码,并将过程的返回地址 ...
- iOS搜索附近的位置(类似微博朋友圈位置)
说什么都是苍白的,直接上图~ 在某些情况下,我们需要获取用户周边的位置,来让用户选取.例如微信的朋友圈,在发一条朋友圈时可以选择地点,就是使用这样的功能. 基于以上的情况(其实也就是为了模仿微信),有 ...
- centos7 安装nginx和php5.6.25遇到 无法访问php页面 报错file not found 问题解决
php-fpm安装完成,nginx安装完成 netstap -ntl| 发下端口正常开启 iptables -L 返现9000端口已经开放 ps -aux|grep nginx 发下nginx进程正常 ...
- jaccard similarity coefficient 相似度计算
Jaccard index From Wikipedia, the free encyclopedia The Jaccard index, also known as the Jaccard ...
- android之服务
android中的进程优先级 前台进程 拥有一个正在与用户交互的Activity(onResume方法被调用) 与一个前台Activity绑定的服务 服务调用了startForeground onCr ...
- 前端框架——BootStrap学习
BootStrap简单总结下:1.栅格系统,能够很好的同时适应手机端和PC端(及传说中的响应式布局) 2.兼容性好 接下来是对BootStrap学习的一些基础案例总结和回顾: 首先引入:bootstr ...