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(详细题解) 线段树
这是个线段树题目,做之前必须要有些线段树基础才行不然你是很难理解的. 此题的难点就是在于你加的数要怎么加,加入你一直加到叶子节点的话,复杂度势必会很高的 具体思路 在增加时,如果要加的区间正好覆盖一个 ...
随机推荐
- Vbox视图热键
Vbox屏幕热键 在Vbox中一般host主键会默觉得"右Ctrl",例如以下图所看到的,在选择自己主动调整窗体后,"视图"选项栏会消失.这时若想更改视图设置能 ...
- HDOJ 5088 Revenge of Nim II 位运算
位运算.. .. Revenge of Nim II Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Ja ...
- 集合简单总结 ArrayList、List、Hashtable、Dictionary
============================ 集合综述 ============================== 1.什么是泛型: 泛型就是限制了操作类型,意思如下: ...
- Flash, Flex, Air, Flashplayer之间的相互关系是什么?
著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处.作者:曾嵘链接:http://www.zhihu.com/question/20001256/answer/15565376来源:知 ...
- perl 继承 @ISA
12.5 类继承 对Perl的对象剩下的内容而言,从一个类继承另外一个类并不需要给这门语法增加特殊的语法,当你调用一个方法的时候, 如果Perl在调用者的包里找不到这个字过程,那么他就检查@ISA数组 ...
- anglehack参赛总结
自已不足的方面: 自已和伙伴是带着idea去的,但是没有带有很大的热情激励和吸引在场的hacker加入团队,一定要找最优秀的人加入团队,事实上我是有这方面识人认人的能力的,24h,5-6个人的优秀团队 ...
- 用python -i写交互式shell
cabinet是公司的一个数据存储服务,需要添加一个shell client,查看数据,做简单操作. 用python写了一个比想象的简单.代码如下: #! /usr/bin/python -i # c ...
- hdu 1421 搬寝室 (dp)
思路分析: dp[i][j] 表示选取到第 i 个 组成了 j 对的最优答案. 当然排序之后 选取相邻两个是更优的. if(i==j*2) dp[i][j] = dp[i-2][j-1] + w[ ...
- 融云(找到“每个App都有沟通的需求”的细分市场)
近日,国内著名App驾考宝典和融云达成合作,为应用增加IM功能,实现亿级用户之间聊天.消息一出,IM(即时通讯)领域的大佬,同时也是个上线不到两岁的新生力量,再次引发了行业的关注. 对业内人士而言,即 ...
- perl lwp编码
$var= $response->content; $var= $response->decoded_content;