poj 3245 Sequence Partitioning(dp+二分+单调队列+sbt)

该博客探讨了POJ 3245题目,涉及数列分割问题。博主提出了解决策略,即根据数列元素的关系进行动态规划合并,并利用二分查找与单调队列来满足限制条件,以找到使B元素和最大化的分段方法。同时,博主提供了问题分析和代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Sequence Partitioning
Time Limit: 8000MS Memory Limit: 65536K
Total Submissions: 710 Accepted: 207
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

Hint

An available assignment is the first two pairs are assigned into the first part and the last two pairs are assigned into the second part. Then  B 1 >  A 3B 1 >  A 4B 2 >  A 3B 2 >  A 4, max{ A 1A 2}+max{ A 3A 4} ≤ 6, and minimum max{ B 1+ B 2B 3+ B 4}=9.

Source

题目:http://poj.org/problem?id=3245

题意:给你一个数列对,其实就是两个数列,你可以把数列分成任意段,要求如下:

1.对于任意元素p和元素q(p<q)在不同段中,那么有Bp>Aq

2.所有段的A元素的最大值的和要小于给定的限制

求满足上面条件下,每个段B元素的和 的最大值


分析:首先考虑第一个限制,我们会发现,只有有数列后面的aj大于等于当前的bi,那么i到j的所有元素必须在一个块,那么就把他们合并,合并就是a取最大值,b取和,具体怎么合并有很多方法,我们可以将b元素的下标,按b从小到大排序,然后反向枚举a元素,标记所有小于a元素的b元素都标记上最大的标号,然后扫描一遍合并所有块

剩下的就是第二个限制了,我们会发现,第二个限制就是这题的反向求解,我们只要二分答案,用之前那题的做法判断可行性就行了


代码:

#include<set>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int mm=55555;
int a[mm],q[mm],p[mm],f[mm],b[mm];
int i,j,n,limit,l,r,m,ans;
multiset<int>sbt;
bool check(int s)
{
    int i,p,l=0,r=-1,tmp;
    __int64 sum=0;
    sbt.clear();
    for(p=i=1;i<=n;++i)
    {
        sum+=b[i];
        while(sum>s)sum-=b[p++];
        if(p>i)return 0;
        while(l<=r&&a[i]>=a[q[r]])
        {
            if(l<r)sbt.erase(f[q[r-1]]+a[q[r]]);
            --r;
        }
        q[++r]=i;
        if(l<r)sbt.insert(f[q[r-1]]+a[q[r]]);
        while(q[l]<p)
        {
            if(l<r)sbt.erase(f[q[l]]+a[q[l+1]]);
            ++l;
        }
        f[i]=f[p-1]+a[q[l]];
        tmp=*sbt.begin();
        if(l<r&&f[i]>tmp)f[i]=tmp;
    }
    return f[n]<=limit;
}
bool cmp(int u,int v)
{
    return b[u]<b[v];
}
int main()
{
    while(~scanf("%d%d",&n,&limit))
    {
        for(i=1;i<=n;++i)
            scanf("%d%d",&a[i],&b[i]),q[i]=p[i]=i;
        sort(p+1,p+n+1,cmp);
        for(j=1,i=n;i>0;--i)
            while(j<=n&&b[p[j]]<=a[i])q[p[j++]]=i;
        for(j=i=1;i<=n;i=l,++j)
        {
            a[j]=a[i],b[j]=b[i];
            for(l=i+1,r=max(q[i],i);l<=r;++l)
            {
                b[j]+=b[l];
                a[j]=max(a[j],a[l]);
                if(q[l]>r)r=q[l];
            }
        }
        n=j-1,l=0,r=2147483647;
        while(l<=r)
        {
            m=(l+r)>>1;
            if(check(m))ans=m,r=m-1;
            else l=m+1;
        }
        printf("%d\n",ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值