Sequence Partitioning
Description Given a sequence of N ordered pairs of positive integers (Ai, Bi), you have to partition it into several contiguous parts. Let p be the number of these parts, whose boundaries are (l1, r1), (l2, r2), ... ,(lp, rp), which satisfy li =ri − 1 + 1, li ≤ ri, l1 = 1, rp = n. The parts themselves also satisfy the following restrictions:
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 (A, B). It's always guaranteed that max{ A 1, A 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
3,
B
1 >
A
4,
B
2 >
A
3,
B
2 >
A
4, max{
A
1,
A
2}+max{
A
3,
A
4} ≤ 6, and minimum max{
B
1+
B
2,
B
3+
B
4}=9.
Source
POJ Monthly--2007.07.08, Chen, Danqi
|
题目: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;
}