| 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 (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:
-
For any two pairs (Ap, Bp), (Aq, Bq), where (Ap, Bp) is belongs to the Tpth part and (Aq, Bq) the Tqth part. If Tp < Tq, then Bp > Aq.
-
Let Mi be the maximum A-component of elements in the ith part, say
Mi = max{Ali, Ali+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 (A, B). It's always guaranteed that
max{ A 1, A 2, ..., An} ≤ LimitOutput
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;
}