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;
}


原文地址:https://www.cnblogs.com/bbsno1/p/3258068.html