zoukankan      html  css  js  c++  java
  • POJ 3017 Cut the Sequence(单调队列+set)

    Cut the Sequence
    Time Limit: 2000MS   Memory Limit: 131072K
    Total Submissions: 7972   Accepted: 2287

    Description

    Given an integer sequence { an } of length N, you are to cut the sequence into several parts every one of which is a consecutive subsequence of the original sequence. Every part must satisfy that the sum of the integers in the part is not greater than a given integer M. You are to find a cutting that minimizes the sum of the maximum integer of each part.

    Input

    The first line of input contains two integer N (0 < N ≤ 100 000), M. The following line contains N integers describes the integer sequence. Every integer in the sequence is between 0 and 1 000 000 inclusively.

    Output

    Output one integer which is the minimum sum of the maximum integer of each part. If no such cuttings exist, output −1.

    Sample Input

    8 17
    2 2 2 8 1 8 2 1

    Sample Output

    12

    Hint

    Use 64-bit integer type to hold M.

    Source

     
     
     
    这题是很好的题目。
    思考了很久一直没有想通。
    后来突然理解了
    可以参照大牛的解释:
    这讲得比较详细了。
     
    /*
     * 用dp[i]表示前i项进行划分得到的结果
     * dp[i]=min{dp[j],max[j+1,i]};
     * 首先假如不考虑m的限制。
     * 那么最优决策的那个j点,一定满足a[j] > max(a[j+1~i])就是j点的值要大于j+1到j点的值。
     * 很明显的结论,因为假如不成立,那么可以把j点也划分到后面去,得到更优的
     * 所以用单调队列维护一个递减数列     a1 a2 a3 a4  ...  a[i] ;a1>a2>a3>a4>a[i];
     * 这样的话最优决策点只能出现在这些点中。
     * 现在加了m的限制。假如上面那个递减数列只有后面一部分是满足m限制的 at,at+1,...a[i].
     * 那么决策点就是上面这些点再加上满足m条件的那个边界。
     * 所以可以用平衡二叉树维护
     * 二叉树里面的值只要随着队列进行维护就好了。
     * 可以用multiset实现。
     */
    
    #include <iostream>
    #include <string.h>
    #include <algorithm>
    #include <stdio.h>
    #include <set>
    using namespace std;
    const int MAXN=100010;
    int a[MAXN];
    long long sum[MAXN];
    int n;
    long long m;
    int q[MAXN];
    int d[MAXN];
    multiset<long long>st;
    multiset<long long>::iterator it;
    long long dp[MAXN];
    void solve()
    {
        int rear,front;
        rear=front=0;
        int decision=0;//限制条件
        st.clear();
        for(int i=1;i<=n;i++)
        {
            while(sum[i]-sum[decision]>m)decision++;
            while(front<rear && q[front]<=decision)//让不符合条件的退出队列
            {
                it=st.find(dp[d[front]]+a[q[front]]);
                st.erase(it);
                front++;
            }
            while(front<rear && a[i]>=a[q[rear-1]])//维护单调队列
            {
                it=st.find(dp[d[rear-1]]+a[q[rear-1]]);
                st.erase(it);
                rear--;
            }
            q[rear]=i;
            if(front<rear)d[rear]=q[rear-1];
            else d[rear]=decision;
            st.insert(dp[d[rear]]+a[i]);
            rear++;
            if(d[front]<decision)//更新那个限制点
            {
                it=st.find(dp[d[front]]+a[q[front]]);
                st.erase(it);
                d[front]=decision;
                st.insert(dp[decision]+a[q[front]]);
            }
            it=st.begin();//最小值
            dp[i]=(*it);
        }
        printf("%I64d\n",dp[n]);
    }
    int main()
    {
    //    freopen("in.txt","r",stdin);
    //    freopen("out.txt","w",stdout);
        while(scanf("%d%I64d",&n,&m)==2)
        {
            bool flag=true;
            sum[0]=0;
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&a[i]);
                sum[i]=sum[i-1]+a[i];
                if(a[i]>m)flag=false;
            }
            if(!flag)
            {
                printf("-1\n");
                continue;
            }
            solve();
        }
        return 0;
    }
     
    人一我百!人十我万!永不放弃~~~怀着自信的心,去追逐梦想
  • 相关阅读:
    2016中国大学生程序设计竞赛
    HDU 1671 Phone List (Trie·数组实现)
    Codeforces Round #367 (Div. 2) Hard problem
    UVA 133 The Dole Queue
    SG函数模板
    Codeforces Round #366 (Div. 2) C Thor(模拟+2种stl)
    [Offer收割]编程练习赛4 A 满减优惠
    CF #365 (Div. 2) D
    Codeforces Round #365 (Div. 2) Chris and Road
    codeblocks AStyle修改格式和快捷键
  • 原文地址:https://www.cnblogs.com/kuangbin/p/3066529.html
Copyright © 2011-2022 走看看