POJ 3245 二分 + DP

159 篇文章 1 订阅
题意

传送门 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:1ip}。二分答案即可,求满足条件一与条件二的最小答案。

条件一:分段

任意两对 ( 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\}\} min1iTx{minlijri{Bj}}>maxTx+1ip{maxlijri{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}\} min1irTx{Bi}>maxrTx+1irp{Ai}

则正向遍历一遍,维护 m i n 1 ≤ j ≤ i { B j } min_{1\leq j\leq i}\{B_{j}\} min1ji{Bj},反向遍历一遍,维护 m a x i + 1 ≤ j ≤ N { A j } max_{i+1\leq j\leq N}\{A_{j}\} maxi+1jN{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}\} min1ji{Bj}>maxi+1jN{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:1ji}x 的最小 ∑ j = 1 i M j \sum\limits_{j=1}^{i}{M_j} j=1iMj。设条件一分段数为 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+1ki{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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值