题意
传送门 POJ 3245
题解
二分答案
S i S_i Si 为部分 i i i 的元素 B j ( j = l i , l i + 1 , … r i ) B_j(j=l_i,l_{i}+1,\dots r_{i}) Bj(j=li,li+1,…ri) 之和,求最小的 m a x { S i : 1 ≤ i ≤ p } max\{S_{i}:1\leq i\leq p\} max{Si:1≤i≤p}。二分答案即可,求满足条件一与条件二的最小答案。
条件一:分段
任意两对 ( A x , B x ) , ( A y , B y ) (A_x,B_x),(A_y,B_y) (Ax,Bx),(Ay,By),若 ( A x , B x ) (A_x,B_x) (Ax,Bx) 属于 T x T_x Tx 部分, ( A y , B y ) (A_y,B_y) (Ay,By) 属于 T y T_y Ty 部分。若 T x < T y T_x<T_y Tx<Ty,则有 B x > A y B_x>A_y Bx>Ay。设序列分为 p p p 部分,对于任意一个部分 T x T_x Tx,满足
m i n 1 ≤ i ≤ T x { m i n l i ≤ j ≤ r i { B j } } > m a x T x + 1 ≤ i ≤ p { m a x l i ≤ j ≤ r i { A j } } min_{1\leq i\leq T_x}\{min_{l_{i}\leq j\leq r_{i}}\{B_j\}\}>max_{T_x+1\leq i \leq p}\{max_{l_{i}\leq j\leq r_{i}}\{A_j\}\} min1≤i≤Tx{minli≤j≤ri{Bj}}>maxTx+1≤i≤p{maxli≤j≤ri{Aj}}
可化简为
m i n 1 ≤ i ≤ r T x { B i } > m a x r T x + 1 ≤ i ≤ r p { A i } min_{1\leq i\leq r_{T_x}}\{B_{i}\}>max_{r_{T_{x}+1}\leq i\leq r_p}\{A_{i}\} min1≤i≤rTx{Bi}>maxrTx+1≤i≤rp{Ai}
则正向遍历一遍,维护 m i n 1 ≤ j ≤ i { B j } min_{1\leq j\leq i}\{B_{j}\} min1≤j≤i{Bj},反向遍历一遍,维护 m a x i + 1 ≤ j ≤ N { A j } max_{i+1\leq j\leq N}\{A_{j}\} maxi+1≤j≤N{Aj},则对于所有满足
m i n 1 ≤ j ≤ i { B j } > m a x i + 1 ≤ j ≤ N { A j } min_{1\leq j\leq i}\{B_{j}\}>max_{i+1\leq j\leq N}\{A_{j}\} min1≤j≤i{Bj}>maxi+1≤j≤N{Aj}
的数对 i i i ,将数对 1 , 2 , … N 1,2,\dots N 1,2,…N 在 i i i 处分割,此时保证分割得到的部分的任意组合一定满足条件一。维护分段 1 , 2 , … i 1,2,\dots i 1,2,…i 的 B B B 的前缀和 s u m [ i ] sum[i] sum[i],以及分段 i i i 内的 A A A 的最大值 s m x [ i ] smx[i] smx[i]。
条件二:DP
设当前二分值为 x x x, d p [ i ] dp[i] dp[i] 代表满足条件一的分段 1 , 2 , … i 1,2,\dots i 1,2,…i 在满足 m a x { S j : 1 ≤ j ≤ i } ≤ x max\{S_{j}:1\leq j\leq i\}\leq x max{Sj:1≤j≤i}≤x 的最小 ∑ j = 1 i M j \sum\limits_{j=1}^{i}{M_j} j=1∑iMj。设条件一分段数为 p a r t part part
d p [ i ] = m i n s u m [ i ] − s u m [ j ] ≤ x { d p [ j ] + m a x j + 1 ≤ k ≤ i { s m x [ k ] } } dp[i]=min_{sum[i]-sum[j]\leq x}\{dp[j]+max_{j+1\leq k\leq i}\{smx[k]\}\} dp[i]=minsum[i]−sum[j]≤x{dp[j]+maxj+1≤k≤i{smx[k]}}
若 d p [ p a r t ] ≤ l i m i t dp[part]\leq limit dp[part]≤limit 则满足条件二;反之,不满足条件二。
复杂度优化
对于最坏复杂度 O ( N 2 l o g ( I N T _ M A X ) ) O(N^2log(INT\_MAX)) O(N2log(INT_MAX)),可以参考 POJ 3017 用单调队列优化 D P DP DP。
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <limits>
using namespace std;
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
#define maxn 50005
int n, limit;
int a[maxn], b[maxn], mn[maxn], mx[maxn];
int part, smx[maxn], sum[maxn], dp[maxn]; // 按条件一的分段数, 各段 max{Ai}, 各段 sum{Bi} 的前缀和, dp
// 求 max{Si} = x 时的最小 sum{Mi}
bool judge(int x)
{
dp[0] = 0;
for (int i = 1; i <= part; i++)
{
int mxa = smx[i], res = INT_MAX;
for (int j = i - 1; j >= 0; j--)
{
if (sum[i] - sum[j] > x) break;
res = min(res, dp[j] + mxa), mxa = max(mxa, smx[j]);
}
if ((dp[i] = res) > limit) return false;
}
return true;
}
int main()
{
scanf("%d%d", &n, &limit);
for (int i = 0; i < n; i++) scanf("%d%d", a + i, b + i);
mn[0] = b[0], mx[n - 1] = a[n - 1];
for (int i = 1; i < n; i++) mn[i] = min(b[i], mn[i - 1]);
for (int i = n - 2; i >= 0; i--) mx[i] = max(a[i], mx[i + 1]);
int mxb = INT_MIN;
part = 0;
// 按条件一分段
for (int pre = 0, i = 0; i < n; i++)
{
if (i == n - 1 || mn[i] > mx[i + 1])
{
++part;
int s = 0, m = INT_MIN;
for (; pre <= i; pre++) s += b[pre], m = max(a[pre], m);
sum[part] = sum[part - 1] + s, mxb = max(mxb, s), smx[part] = m;
}
}
// 二分答案
int lb = mxb - 1, ub = sum[part];
while (ub - lb > 1)
{
int mid = (ub + lb) >> 1;
if (judge(mid)) ub = mid;
else lb = mid;
}
printf("%d\n", ub);
return 0;
}