• poj 3245 Sequence Partitioning


    Sequence Partitioning
    Time Limit: 8000MS   Memory Limit: 65536K
    Total Submissions: 922   Accepted: 256
    Case Time Limit: 5000MS

    Description

    Given a sequence of N ordered pairs of positive integers (AiBi), you have to partition it into several contiguous parts. Let p be the number of these parts, whose boundaries are (l1r1), (l2r2), ... ,(lprp), which satisfy l=ri − + 1, l ril1 = 1, rn. The parts themselves also satisfy the following restrictions:

    1. For any two pairs (ApBp), (Aq, Bq), where (Ap, Bp) is belongs to the Tpth part and (AqBq) the Tqth part. If Tp < Tq, then B> Aq.

    2. Let Mi be the maximum A-component of elements in the ith part, say

      Mi = max{AliAli+1, ..., Ari}, 1 ≤ i ≤ p

      it is provided that

      where Limit is a given integer.

    Let Si be the sum of B-components of elements in the ith part. Now I want to minimize the value

    max{Si:1 ≤ i ≤ p}

    Could you tell me the minimum?

    Input

    The input contains exactly one test case. The first line of input contains two positive integers N (N ≤ 50000), Limit (Limit ≤ 231-1). Then follow N lines each contains a positive integers pair (AB). It's always guaranteed that

    max{ A 1A 2, ...,  An} ≤ Limit

    Output

    Output the minimum target value.

    Sample Input

    4 6
    4 3
    3 5
    2 5
    2 4
    

    Sample Output

    9
    这题目真是坑啊,读了老半天,我们发现这有两个条件
    1要前面部分的b大于后面的a,那么我们一定可以得到,如果有个ai小于前面的bj,那么一定要将i到j合并,我们先按b来排序,这样我们就要要找到所有大于当前b[i]的a的最大下标,按这个最大下标合并成一项就可以了,合并就是a取最大的,b取和就可以了!
    2就是最小和了,我们可以发现这处的poj3017是相反的,因为poj3017的答案正是这题的要求,而这题的限制,正是那题的答案,所以我们用二分枚举就可以转化成那题来做了!
    #include <stdio.h>
    #include <iostream>
    #include <algorithm>
    #include <stdio.h>
    #include <set>
    #define MAXN 50050
    using namespace std;
    int dp[MAXN],a[MAXN],b[MAXN],minb[MAXN],maxa[MAXN];
    int n,limit,queue[MAXN*3];
    set<int > myset;
    bool cmp(int i,int j)
    {
        return b[i]<b[j];//按b的大小来排序
    }
    int fmin(int i,int j)
    {
        if(i<j)
        return i;
        return j;
    }
    int fmax(int i,int j)
    {
        if(i>j)
        return i;
        return j;
    }
    bool can(int sum)
    {
        int i,s,e,ss,p;
        s=0;e=-1;
        myset.clear();
        dp[0]=0;
        for(i=1,ss=0,p=1;i<=n;i++)
        {
            ss+=b[i];
            while(ss>sum)
            {
                ss=ss-b[p++];
            }
            if(p>i)
            return false;
            while(s<=e&&a[queue[e]]<=a[i])
            {
    
                if(s<e)
                myset.erase(dp[queue[e-1]]+a[queue[e]]);
                e--;
            }
            queue[++e]=i;
            if(s<e)
            myset.insert(dp[queue[e-1]]+a[queue[e]]);
            while(s<=e&&queue[s]<p)
            {
                if(s<e)
                {
                    myset.erase(dp[queue[s]]+a[queue[s+1]]);
                }
                s++;
    
            }
            dp[i]=dp[p-1]+a[queue[s]];
            if(s<e)
            {
                dp[i]=fmin(dp[i],*myset.begin());
            }
        }
        return dp[n]<=limit;
    }
    int main ()
    {
        int i,j; int k,r,l,m;
        while(scanf("%d%d",&n,&limit)!=EOF)
        {
          
            for(i=1;i<=n;i++)
            {
                scanf("%d%d",&a[i],&b[i]);
                minb[i]=maxa[i]=i;
            }
            sort(minb+1,minb+n+1,cmp);
            for(i=1,j=n;j>0;j--)
            {
                while(i<=n&&b[minb[i]]<=a[j])
                {
                    maxa[minb[i]]=j;
                    i++;
                }
            }
            for(i=1,j=1;j<=n&&i<=n;i=r+1,j++)
            {
                a[j]=a[i];b[j]=b[i];
                for(k=i+1,r=fmax(i,maxa[i]);k<=r;k++)
                {
                    a[j]=fmax(a[j],a[k]);
                    b[j]+=b[k];
    
                }
            }
            
            n=j-1;//n已转换了
            l=0;r=(1<<31)-1;
            int ans;
            while(l<=r)
            {
                m=(l+r)>>1;
                if(can(m))
                {
                    ans=m;
                    r=m-1;
                }
                else
                {
                    l=m+1;
                }
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    


  • 相关阅读:
    『Python基础』第4节:基础数据类型初识
    『Python基础练习题』day02
    『Python基础』第1节 Windows环境下安装Python3.x
    Windows安装Mysql5.7.22
    jar 运行报错:找不到或无法加载主类
    linux 下的mysql 连接报错
    将本地Jar包安装到maven仓库中去
    Mysql 中的伪列用法
    Mysql 中的伪列用法1
    关于springboot中文件上传,properties配置
  • 原文地址:https://www.cnblogs.com/bbsno1/p/3258068.html
Copyright © 2020-2023  润新知