HDU 3415 Max Sum of Max-K-sub-sequence
Posted zzhzzh123
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 3415 Max Sum of Max-K-sub-sequence相关的知识,希望对你有一定的参考价值。
题目大意:
我们有一个环状的数列,内有n个元素,现在其中找一长度不超过k的连续子序列,使值最大.
分析:
原数组断环为链:
(A_1)..(A_n) = > (A_1).. (A_n A_{n+1})..(A_{n+k})
考虑一段连续的子序列的值就是前缀和相减的形式
我们得到前缀和数组
(S_1)..(S_{n+k})
考虑以i为右端点的子序列,共有k种,值分别是(S_i-S_{i-1}),(S_i-S_{i-2})...(S_i-S_{i-k})
显然我们要在这之中找一个最大值,即在(S_{i-1}),(S_{i-2})...(S_{i-k})中找一个最小值
问题转化成对于每个(S_i),在某一定长区间内找一最小值
ST表,线段树均可在(O(nlogn))的时间内解决
但是还可以更快,用单调队列
[Code]
#include <bits/stdc++.h>
using namespace std;
int read(){
int x=0,flag=1; char c;
for(c=getchar();!isdigit(c);c=getchar()) if(c=='-') flag=-1;
for(;isdigit(c);c=getchar()) x=((x+(x<<2))<<1)+(c^48);
return x*flag;
}
const int N=2e5+50;
int n,k;
int a[N];
int s[N];
int main() {
int T=read();
while(T--){
n=read(),k=read();
for(int i=1;i<=n;i++) a[i]=read();
for(int i=n+1;i<=n+k+1;i++) a[i]=a[i-n];
for(int i=1;i<=n+k+1;i++) s[i]=s[i-1]+a[i];
int ans=-2e9;
int l=-1,r=-1;
deque<int> q;
q.push_back(0);
for(int i=1;i<=n+k+1;i++){
while(!q.empty()&&i-q.front()>k) q.pop_front();
if(s[i]-s[q.front()]>ans){
ans=s[i]-s[q.front()];
l=q.front()+1; r=i;
}
ans=max(ans,s[i]-s[q.front()]);
while(!q.empty()&&s[q.back()]>=s[i]) q.pop_back();
q.push_back(i);
}
if(l>n) l-=n;
if(r>n) r-=n;
printf("%d %d %d
",ans,l,r);
}
return 0;
}
以上是关于HDU 3415 Max Sum of Max-K-sub-sequence的主要内容,如果未能解决你的问题,请参考以下文章
HDU 3415 Max Sum of Max-K-sub-sequence
HDU 3415 Max Sum of Max-K-sub-sequence 单调队列题解