jzoj3463-军训【双重嵌套二分,随机数据水法】

83 篇文章 0 订阅

正题


大意

每个人有两个值 gi g i hi h i ,要求将序列分解成连续的几个序列。要求每个序列最大的 hi h i 的和小于Limt的情况下每个序列 gi g i 的和的最大值最小。


解题思路

我们二分最小的 gi g i 的和的最大值
首先一个 O(n2) O ( n 2 ) 的dp想法,用 fi f i 表示分割到第i个时最大的 hi h i 的和的最小值。
动态转移:

fi=min{f[j]+max{hj,hj+1,hj+2...hi1,hi}} f i = m i n { f [ j ] + m a x { h j , h j + 1 , h j + 2 . . . h i − 1 , h i } }

我们考虑如何优化,每次有新的max只会在产生更大的 hi h i 时,于是我们可以用一个 nexti n e x t i 表示最近的 hnext>hi h n e x t > h i ,然后我们可以二分快速找到满足小于你目前二分到的答案的最小的位置。
时间复杂度 O(n2+n  (log n)2) O ( n 2 + n     ( l o g   n ) 2 )
是不是感觉时间复杂度没有变化,巧了!它就是A了


代码

#include<cstdio>
#include<algorithm>
#include<cstring>
#define H 20010
#define ll long long
using namespace std;
int n,h[H],g[H],z[H],next[H],num[H],tot;
ll sum[H],L,f[H],ans,l,r;
int find(int x,int need)//二分满足条件的最小值
{
    int l=x,r=n;
    while(l<r)
    {
        int mi=(l+r)/2;
        if(sum[mi]-sum[x-1]>=need) r=mi;
        else l=mi+1;
    }
    return l;
}
bool check(int x)
{
    memset(f,127/3,sizeof(f));
    f[1]=0;
    for (int i=1;i<=n;i++)//dp
    {
        int k=find(i,x),y=i,add=h[y];
        if (sum[k]-sum[i-1]>x) k--;
        while(y<=k)
        {
            f[y]=min(f[y],f[i]+add);
            add=h[y];
            y=next[y];
        }
        f[k+1]=min(f[k+1],f[i]+add);
    }
    return f[n+1]<=L;
}
int main()
{
    scanf("%d%lld",&n,&L);
    for(int i=1;i<=n;i++)
    {
      scanf("%d%d",&h[i],&g[i]);
      sum[i]=sum[i-1]+g[i];
    }
    num[1]=n+1;z[1]=2147483647;tot=1;
    for (int i=n;i;i--)//暴力next数组
    {
        while (z[tot]<=h[i]) tot--;
        next[i]=num[tot];++tot;
        num[tot]=i;z[tot]=h[i];
    } 
    l=1;r=sum[n];ans=r;
    while(l<=r)//二分
    {
        int mid=(l+r)>>1;
        if (check(mid)) {
            if (mid<ans)ans=mid;
            r=mid-1;
        }
        else l=mid+1;
    }
    printf("%lld",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值