POJ 3415 Max Sum of Max-K-sub-sequence (线段树+dp思想)
Max Sum of Max-K-sub-sequence
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5084 Accepted Submission(s): 1842
Now your job is to calculate the max sum of a Max-K-sub-sequence. Max-K-sub-sequence means a continuous non-empty sub-sequence which length not exceed K.
Then T lines follow, each line starts with two integers N , K(1<=N<=100000 , 1<=K<=N), then N integers followed(all the integers are between -1000 and 1000).
6 3
6 -1 2 -6 5 -5
6 4
6 -1 2 -6 5 -5
6 3
-1 2 -6 5 -5 6
6 6
-1 -1 -1 -1 -1 -1
7 1 3
7 6 2
-1 1 1
题目大意:T 组数据,求 n 个数 连续子串的最大和是多少,子串要求长度不超过 k,以及这是个环形,如果多解,满足起点be最小,其次终点en最小
解题思路:枚举每个起点be,终点en一定是在 be<=en<=be+k-1 这个范围内,所以求这个范围内的连续最长和即可,可以用 sum[en] -sum[be-1] ,其中sum[x]表示前x个数的和,所以即选出 be<=en<=be+k-1这个范围内最大sum[i],用线段树过了,但是rmq算法超时,郁闷!
线段树算法,AC
#include <iostream>
#include <cmath>
#include <cstdio>
using namespace std; const int maxn=200010;
int d[maxn],sum[maxn],n,k,mx,mn; struct node{
int l,r,minc,maxc;
}a[4*maxn]; void input(){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%d",&d[i]);
d[i+n]=d[i];
}
sum[0]=0;
for(int i=1;i<=2*n;i++) sum[i]=sum[i-1]+d[i];
} void build(int l,int r,int k){
a[k].l=l;
a[k].r=r;
if(l<r){
int mid=(l+r)/2;
build(l,mid,2*k);
build(mid+1,r,2*k+1);
a[k].maxc=max(a[2*k].maxc,a[2*k+1].maxc);
a[k].minc=min(a[2*k].minc,a[2*k+1].minc);
}else{
a[k].maxc=sum[l];
a[k].minc=sum[l];
}
} void query(int l,int r,int k){
if(l<=a[k].l && a[k].r<=r){
//cout<<a[k].maxc<<" "<<a[k].minc<<endl;
mx=max(mx,a[k].maxc);
mn=min(mn,a[k].minc);
}else{
int mid=(a[k].l+a[k].r)/2;
if(r<=mid) query(l,r,2*k);
else if(l>=mid+1) query(l,r,2*k+1);
else{
query(l,mid,2*k);
query(mid+1,r,2*k+1);
}
}
} void computing(){
build(0,2*n,1);
int ans=-(1<<30),be=1,en=1;
for(int i=1;i<=n;i++){
mx=-(1<<30);
query(i,i+k-1,1);
if(mx-sum[i-1]>ans){
ans=mx-sum[i-1];
be=i;
}
}
for(int i=be;i<=be+k-1;i++){
if(sum[i]-sum[be-1]==ans){
en=i;
break;
}
}
printf("%d %d %d\n",ans,be>n?be-n:be,en>n?en-n:en);
} int main(){
int t;
scanf("%d",&t);
while(t-- >0){
input();
computing();
}
return 0;
}
rmq算法,超时,郁闷中
#include <iostream>
#include <cmath>
#include <cstdio>
using namespace std; const int maxn=300005*2;
int maxsum[maxn][20],minsum[maxn][20],flog[maxn],d[maxn],sum[maxn],n,k; void ini(){
int r=2,cnt=0;
for(int i=1;i<maxn;i++){
if(i<r) flog[i]=cnt;
else{
flog[i]=++cnt;
r=r<<1;
}
}
} void input(){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%d",&d[i]);
d[i+n]=d[i];
}
} void getrmq(){
for(int i=1;i<=2*n;i++){
sum[i]=sum[i-1]+d[i];
maxsum[i][0]=sum[i];
minsum[i][0]=sum[i];
}
for(int j=1;j<=flog[2*n];j++)
for(int i=1;i<=2*n;i++){
if(i+(1<<j)-1<=2*n){
maxsum[i][j]=max(maxsum[i][j-1],maxsum[i+(1<<(j-1))][j-1]);
minsum[i][j]=min(minsum[i][j-1],minsum[i+(1<<(j-1))][j-1]);
}
}
} void computing(){
getrmq();
int ans=-(1<<30),be=1,en=1,l,r,x,tmp;
for(int i=1;i<=n;i++){
l=i,r=i-1+k,x=flog[r-l+1];
tmp=max(maxsum[l][x],maxsum[r-(1<<x)+1][x]);
if(tmp-sum[i-1]>ans){
ans=tmp-sum[i-1];
be=i;
}
}
for(int i=be;i<=be+k-1;i++){
if(sum[i]-sum[be-1]==ans){
en=i;
break;
}
}
printf("%d %d %d\n",ans,be>n?be-n:be,en>n?en-n:en);
} int main(){
ini();
int t;
scanf("%d",&t);
while(t-- >0){
input();
computing();
}
return 0;
}
POJ 3415 Max Sum of Max-K-sub-sequence (线段树+dp思想)的更多相关文章
- POJ 2014.K-th Number 区间第k小 (归并树)
K-th Number Time Limit: 20000MS Memory Limit: 65536K Total Submissions: 57543 Accepted: 19893 Ca ...
- 【CF280D】k-Maximum Subsequence Sum(大码量多细节线段树)
点此看题面 大致题意: 给你一个序列,让你支持单点修改以及询问给定区间内选出至多\(k\)个不相交子区间和的最大值. 题意转换 这道题看似很不可做,实际上可以通过一个简单转换让其变可做. 考虑每次选出 ...
- K - Japan(线段树)
Japan plans to welcome the ACM ICPC World Finals and a lot of roads must be built for the venue. Jap ...
- Codeforces 1303G - Sum of Prefix Sums(李超线段树+点分治)
Codeforces 题面传送门 & 洛谷题面传送门 个人感觉这题称不上毒瘤. 首先看到选一条路径之类的字眼可以轻松想到点分治,也就是我们每次取原树的重心 \(r\) 并将路径分为经过重心和不 ...
- poj 2777(线段树+lazy思想) 小小粉刷匠
http://poj.org/problem?id=2777 题目大意 涂颜色,输入长度,颜色总数,涂颜色次数,初始颜色都为1,然后当输入为C的时候将x到y涂为颜色z,输入为Q的时候输出x到y的颜色总 ...
- POJ 2750 Potted Flower(线段树+dp)
题目链接 虽然是看的别的人思路,但是做出来还是挺高兴的. 首先求环上最大字段和,而且不能是含有全部元素.本来我的想法是n个元素变为2*n个元素那样做的,这样并不好弄.实际可以求出最小值,总和-最小,就 ...
- bzoj3110 [Zjoi2013]K大数查询——线段树套线段树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3110 外层权值线段树套内层区间线段树: 之所以外层权值内层区间,是因为区间线段树需要标记下传 ...
- bzoj 3110 [Zjoi2013]K大数查询——线段树套线段树(标记永久化)
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3110 第一道线段树套线段树! 第一道标记永久化! 为什么为什么写了两个半小时啊…… 本想线段 ...
- POJ 3468 A Simple Problem with Integers(详细题解) 线段树
这是个线段树题目,做之前必须要有些线段树基础才行不然你是很难理解的. 此题的难点就是在于你加的数要怎么加,加入你一直加到叶子节点的话,复杂度势必会很高的 具体思路 在增加时,如果要加的区间正好覆盖一个 ...
随机推荐
- P65
#include<stdio.h> #define N 6 main() { char c[N]; int i=0; for(;i<N;c[i]=getchar(),i++); pr ...
- Tuxedo入门学习
中间件介绍: 介于客户机和server之间的夹层,突破了传统的c/s架构,为构建大规模,高性能,分布式c/s应用程序提供了通信,事物,安全,容错等基础服务,屏蔽了底层应用细节,应用程序不必从底层开发, ...
- hdu 4940 Destroy Transportation system( 无源汇上下界网络流的可行流推断 )
题意:有n个点和m条有向边构成的网络.每条边有两个花费: d:毁坏这条边的花费 b:重建一条双向边的花费 寻找这样两个点集,使得点集s到点集t满足 毁坏全部S到T的路径的费用和 > 毁坏全部T到 ...
- SQL Server 存储过程、触发器、游标
存储过程 1.存储过程是事先编好的.存储在数据库中的程序,这些程序用来完成对数据库的指定操作. 2.系统存储过程: SQL Server本身提供了一些存储过程,用于管理有关数据库和用户的信息. 用户存 ...
- C++ 左值 右值
最近在研究C++ 左值 右值,搬运.收集了一些别人的资料,供自己记录和学习,若以后看到了更好的解释,会继续补充.(打“?”是我自己不明白的地方 ) 参考:<Boost程序库探秘——深度解析C ...
- Cocos2dx系列笔记7:一个简单的跑酷游戏《萝莉快跑》的消化(附下载)
懒骨头(http://blog.csdn.com/iamlazybone) 或许有天 我们羡慕和崇拜的人 因为我们的努力 也会来了解我们 说不定 还会成为好友 骨头喜欢这样与哲哲共勉 多少个夜晚 一张 ...
- 华为手机logcat不出日志解决方案
解决方法:在拨打电话界面,录入*#*#2846579#*#* 自动进入开发界面菜单,进入第一个,选择开启logcat.
- Qt递归拷贝和删除目录
最近在翻看项目代码时,看到了这两个函数,想到这个功能十分常用,因此拿出来与大家分享,希望对大家有用.几点说明: 1.记得当初写代码那会,是参考了网上的帖子写的,做了一点小修改.因此代码源于网络. 2. ...
- axure网格设置
Axure默认的界面是没有吧网格显示出来,没有网格在制作原型的时候,对齐方面不是很好,个人习惯还是把网格显示出来,便于组件对齐和布局. 其实本来这篇文章应该叫做网格与参考线,只是本人对参考线的应用还很 ...
- [cocos2d-x]HelloWorldDemo
实现一个demo,具备以下功能: 1.让几个字分别位于中间和四个角落. 2.中间的字体改变,并且带有闪烁功能. 3.单点触摸和多点触摸,并且能够实现滑动效果,滑动的话必须使用带有bool返回值的单点触 ...