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(详细题解) 线段树
这是个线段树题目,做之前必须要有些线段树基础才行不然你是很难理解的. 此题的难点就是在于你加的数要怎么加,加入你一直加到叶子节点的话,复杂度势必会很高的 具体思路 在增加时,如果要加的区间正好覆盖一个 ...
随机推荐
- LoadRunner 监控 Apache
配置Apache部分 1.修改Apache中Httpd.conf文件 <Location /server-status> SetHandler server-status Order de ...
- POJ 2404 Jogging Trails
Jogging Trails Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 2122 Accepted: 849 Des ...
- JAVA EE 项目经常使用知识 之AJAX技术实现select下拉列表联动的两种使用方法(让你真正理解ajax)
ajax 下拉列表联动的使用方法. ajax的定义: AJAX 是一种用于创建高速动态网页的技术. 通过在后台与server进行少量数据交换,AJAX 能够使网页实现异步更新.这意味着能够在不又一次载 ...
- poj 3266 Cow School 分数规划
这个题目难度非常大,首先对于老师的一种方案,应用分数规划的一般做法,求出所有的c=t-rate*p,如果没有选择的c值中的最大值比选择了的c值中的最小值大,那么这个解是可以改进的. 那么问题就转化成了 ...
- CentOS 配置 ssh
默认安装ssh是有的.只是hosts访问问题. 1.在hosts.deny文件尾添加sshd:ALL意思是拒绝所有访问请求 [root@localhost ~]# vi /etc/hosts.de ...
- 怎样在ios开发中设置tableview的cell颜色
//方法一: cell .contentView .backgroundColor = [ UIColor redColor ]; //方法二: UITableViewCell *cell = [ta ...
- ASP.NET - 网页重定向 Response.Redirect()
在网页中使用重定向,意思就是在网站中的某一个页面跳转到另一个页面. Response.Redirect(~/abc.aspx); 使用“~”的作用是可以从任意位置跳转. 如果没有“~”,那么跳转的时候 ...
- (摘录)26个ASP.NET常用性能优化方法
数据库访问性能优化 数据库的连接和关闭 访问数据库资源需要创建连接.打开连接和关闭连接几个操作.这些过程需要多次与数据库交换信息以通过身份验证,比较耗费服务器资源. ASP.NET中提供了连接池(Co ...
- 最长公共子序列python实现
最长公共子序列是动态规划基本题目,以下依照动态规划基本步骤解出来. 1.找出最优解的性质,并刻划其结构特征 序列a共同拥有m个元素,序列b共同拥有n个元素,假设a[m-1]==b[n-1],那么a[: ...
- WebService 之 WSDL文件 解说
恩,我想说的是,是不是常常有人在开发的时候,特别是和第三方有接口的时候,走的是SOAP协议,然后用户给你一个WSDL文件,说依照上面的进行适配,嘿嘿,这个时候,要是你曾经没有开发过,肯定会傻眼,那假设 ...