HU 3415 Max Sum of Max-K-sub-sequence(DP+単調なキュー)
1554 ワード
テーマリンク:
http://acm.hdu.edu.cn/showproblem.php?pid=3415
件名:
長さnのリングを指定します.その中の一つの長さがkに等しい区間より小さいことを求めて、それを最大にして、出力は最大と区間の左右の端点です.
分析:
直接暴力dp[i]=sum[i]-sum[i-k+1+j]を思い付きます. (0<=j==k)
しかし、明らかに暴力がタイムアウトします.単独でキューを使ってメンテナンスしたいです.sum配列です.
sumをできるだけ小さくして前にします.処理するときは環を展開します.sumはプレフィックスと預けられます.
コードは以下の通りです
http://acm.hdu.edu.cn/showproblem.php?pid=3415
件名:
長さnのリングを指定します.その中の一つの長さがkに等しい区間より小さいことを求めて、それを最大にして、出力は最大と区間の左右の端点です.
分析:
直接暴力dp[i]=sum[i]-sum[i-k+1+j]を思い付きます. (0<=j==k)
しかし、明らかに暴力がタイムアウトします.単独でキューを使ってメンテナンスしたいです.sum配列です.
sumをできるだけ小さくして前にします.処理するときは環を展開します.sumはプレフィックスと預けられます.
コードは以下の通りです
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn = 100010;
int a[maxn*2],sum[maxn*2];
int main()
{
int t,n,k;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&k);
memset(sum,0,sizeof(sum));
for(int i=1;i<=n;i++){
scanf("%d",a+i);
sum[i]=sum[i-1]+a[i];
a[i+n]=a[i];
}
for(int i=n+1;i<=2*n;i++)
sum[i]=sum[i-1]+a[i];
deque<int >Q;
int ans = -1000000000,st=0,ed=0;
for(int i=1;i<=n+k-1;i++){
while(!Q.empty()&&sum[i-1]<sum[Q.back()])//
Q.pop_back();
while(!Q.empty()&&Q.front()<i-k)// k
Q.pop_front();
Q.push_back(i-1);
if(sum[i]-sum[Q.front()]>ans){
ans=sum[i]-sum[Q.front()];
st=Q.front()+1;
ed=i;
}
}
if(ed>n) ed-=n;
printf("%d %d %d
",ans,st,ed);
}
return 0;
}