• poj 3017 Cut the Sequence dp


           dp[k]是非递增的,然后对于同样的转移代价,我们只需要找到i最小的dp[i]及可。

     所以可以用单调队列维护一个递减的序列,存储转移代价,即一段中的最大值。对于每个转移代价下的dp[i]+a[j],把它压入set中。每次找到最小的值来更新dp[k]。

            维护队列,set,有比较麻烦的边界条件,要好好处理。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <set>
    using namespace std;
    const int maxn=1e5+9;
    typedef long long ll;
    multiset <ll> d;
    ll n,m;
    int a[maxn];
    struct
    {
        int id,data;
    }que[maxn];
    long long dp[maxn];
    int main()
    {
        d.insert((ll)1<<50);
        scanf("%lld %lld",&n,&m);
        for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    
        int st=1,ed=0,low=1;
        long long sum=0;
    
        for(int i=1;i<=n;i++)
        {
            if(a[i]>m)
            {
                printf("-1\n");
                return 0;
            }
            sum+=a[i];
            while(sum>m) sum-=a[low++];
    
            while(ed>=st&&a[i]>=que[ed].data)
            {
               if(ed>st) d.erase(d.find(dp[que[ed-1].id]+a[que[ed].id]));
                ed--;
            }
    
            if(ed>=st) d.insert(dp[que[ed].id]+a[i]);
            que[++ed].data=a[i];
            que[ed].id=i;
            while(que[st].id<low&&ed>=st)
            {
                if(st<ed) d.erase(d.find(dp[que[st].id]+a[que[st+1].id]));
                st++;
            }
    
            long long tmp=min(*d.begin(),dp[low-1]+que[st].data);
            dp[i]=tmp;
        }
    
        printf("%lld",dp[n]);
        return 0;
    }
    



  • 相关阅读:
    UVA 254 Towers of Hanoi
    UVA 701 The Archeologists' Dilemma
    UVA 185 Roman Numerals
    UVA 10994 Simple Addition
    UVA 10570 Meeting with Aliens
    UVA 306 Cipher
    UVA 10160 Servicing Stations
    UVA 317 Hexagon
    UVA 10123 No Tipping
    UVA 696 How Many Knights
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3057328.html
Copyright © 2020-2023  润新知