您的位置:首页 > 产品设计 > UI/UE

hdu3415 Max Sum of Max-K-sub-sequence 单调队列

2015-07-23 11:31 691 查看
//hdu3415 Max Sum of Max-K-sub-sequence
//单调队列
//首先想到了预处理出前缀和利用s[i] - s[j]表示(j,i]段的和
//之后的问题就转换成了求一个最小的s[j]了,这样就可以单调队列
//求最小值。

//队列中维护的是区间的开始的位置j,我们插入队列中的是j-1,因为
//这个时候s[i] - s[j-1]刚好就是[j,i]段闭区间的和

//这里用两种方式实现,一种是stl,一种是手动模拟,两者的速度,测试的
//结果在杭电测试都是一样的,499ms。
//
//单调队列的路还长着,继续走吧

#include <cstdio>
#include <queue>
#include <algorithm>
#include <iostream>
#include <cstring>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 8;
ll a[maxn*2];
ll sum[maxn*2];
ll x[maxn * 2];
int deq[maxn * 2];
int n,k;
int mod;
void input(){
    scanf("%d%d",&n,&k);
    for (int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
    }
    for (int i=n+1;i<=2*n;i++){
        a[i] = a[i-n];
    }

    sum[0] = 0;

    for (int i=1;i<=n;i++){
        sum[i] = sum[i-1] + a[i];
    }

    for (int i=1;i<k;i++){
        sum[i+n]= sum[i+n-1] + a[i];
    }
    mod = n;
    n = n + k - 1;

}

void solve(){
    int s,e;
    int head = 0,tail = 0;
    ll mx = -1e10;
    for (int i=1;i<=n;i++){
        while(tail > head && sum[i-1]<=sum[deq[tail-1]])
            tail--;
        while(tail > head && deq[head]<i-k)
            head++;
        deq[tail++] = i-1;
        if (sum[i] - sum[deq[head]] > mx){
            mx = sum[i] - sum[deq[head]];
            s = deq[head] + 1;
            e = i;
        }
    }

    if (e > mod)
        e -= mod;
    printf("%lld %d %d\n",mx,s,e);

    //printf("%lld %d\n",x[mk],(mk+k)%n);
}

//void solve(){
//    int s,e;
//    deque<int> deq;
//    deq.clear();
//    ll mx = -1e10;
//    for (int i=1;i<=n;i++){
//        while(!deq.empty() && sum[i-1]<=sum[deq.back()])
//            deq.pop_back();
//        while(!deq.empty() && deq.front()<i-k)
//            deq.pop_front();
//        deq.push_back(i-1);
//        if (sum[i] - sum[deq.front()]>mx){
//            mx = sum[i] - sum[deq.front()];
//            s = deq.front() + 1;
//            e = i;
//        }
//    }
//
//    if (e > mod)
//        e -= mod;
//    printf("%lld %d %d\n",mx,s,e);
//
//    //printf("%lld %d\n",x[mk],(mk+k)%n);
//}

int main(){
    //freopen("1.txt","r",stdin);
    int t;
    scanf("%d",&t);
    while(t--){
        input();
        solve();
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: