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