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;
    }
     
    人一我百!人十我万!永不放弃~~~怀着自信的心,去追逐梦想
  • 相关阅读:
    URAL 2046 A
    URAL 2056 Scholarship 水题
    Codeforces Gym 100286I iSharp 水题
    Codeforces Gym H. Hell on the Markets 贪心
    Codeforces Gym 100286G Giant Screen 水题
    Codeforces Gym 100286B Blind Walk DFS
    Codeforces Gym 100286F Problem F. Fibonacci System 数位DP
    Codeforces Gym 100286A. Aerodynamics 计算几何 求二维凸包面积
    Codeforces Gym 100418K Cards 暴力打表
    Codeforces Gym 100418J Lucky tickets 数位DP
  • 原文地址:https://www.cnblogs.com/kuangbin/p/3066529.html
Copyright © 2011-2022 走看看