poj 3245 Sequence Partitioning

来源:互联网 发布:电脑软件开发 编辑:程序博客网 时间:2024/06/06 06:43
Sequence Partitioning
Time Limit: 8000MS Memory Limit: 65536KTotal Submissions: 922 Accepted: 256Case 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{A1A2, ..., An} ≤ Limit

Output

Output the minimum target value.

Sample Input

4 64 33 52 52 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 50050using 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\n",ans);    }    return 0;}