poj 3017 Cut the Sequence dp 單調隊列+set

http://poj.org/problem?id=3017

poj  3017 Cut the Sequence

 

 對我來說……挺不好理解的一道題…………

 

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <set>
using namespace std;
const int maxn= 100005;
const int INF= 0x3f3f3f3f;
long long dp[maxn], m;
int a[maxn], n, q[maxn];
multiset<long long> tree;
void dynamic(){
    int i, j, k, h, r, lef= 1, flag= 1;
    long long sum= 0;
    h= 0, r= -1;
    /*
        狀態轉移方程:
        dp[i]= dp[lef-1] + max(a[lef]...a[i])
        用單調隊列q維護區間最大點,元素值及下標都單調遞減
        sbt維護最優值,堆頂爲最小值
    */
    for( i= 1; i<= n; i++){
        sum+= a[i];
        while( sum > m) sum-= a[lef++]; //求最左可以分爲一組的點
        if( lef > i){
            flag= 0;
            break;
        }
        while( h <= r && a[q[r]] <= a[i] ){//單調隊列中找到i的位置
            /*
                刪除sbt中不符合的數據
                若去q[r]刪除掉,則對應的sbt中的dp[q[r-1]] + a[q[r]]項也應去掉
                其中,a[q[r]]爲[q[r], i-1]的最大值,但a[q[r]]同樣也大於a[q[r-1]]
                即dp[i-1]= dp[a[q[r-1]]] + max(a[q[r-1]]...a[q[r]]...a[i-1])爲sbt中被刪除的值
            */
            if( h < r)
                tree.erase(dp[q[r-1]] + a[q[r]]);
            r--;
        }
        q[++r]= i; //i點存入隊列
        if( h < r) tree.insert( dp[q[r-1]] + a[q[r]]);//新更新的隊列的隊首值加入隊列,但不一定是目前最優值
        while( q[h] < lef){// 隊首元素不在區間內時刪除,維護單調隊列取值在規定範圍內
            if( h < r)
                tree.erase( dp[q[h]] + a[q[h+1]]);//sbt中刪除不在範圍內的點的值,a[q[h+1]]爲(q[h], i]中的最大值
            h++;
        }
        dp[i]= dp[lef-1] + a[q[h]]; //下限值特判
        if( h < r && dp[i] > *(tree.begin())) dp[i]= *tree.begin();
        cout<<i<<"  "<<dp[i]<<"  "<<dp[lef-1] + a[q[h]]<<"  "<<(*tree.begin())<<endl;;
    }
    if( flag)printf("%I64d\n", dp[n]);
    else printf("-1\n");
}
int main(){
   //freopen("1.txt", "r", stdin);
    int i, j, k;
    while( scanf("%d%I64d", &n, &m) != EOF){
        a[0]= dp[0]= 0;
        for( i= 1; i<= n; i++){
            scanf("%d", &a[i]);
        }
        dynamic();
    }
    return 0;
}
發佈了69 篇原創文章 · 獲贊 1 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章