• CF487 B. Strip


    Problem - 487B - Codeforces

     

    题意:

    一个n个数的数组,要求把他们划分为最少的连续段,满足:

    1、每段长度至少为l

    2、每段的最大值-最小值不超过s

     

    dp[i]表示前i个数最少要划分为多少段

    枚举j(j<=i-l),若[j+1,i]的最大值-最小值不超过s,那么dp[i]=min(dp[i],dp[j]+1)

    枚举j是n^2的,可以二分出满足极值差要求的区间,然后用线段树优化

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define N 100003
    
    int mx[N<<2],mi[N<<2],dp[N<<2];
    int qm,qi,w;
    
    void build(int k,int l,int r)
    {
        dp[k]=2e9;
        if(l==r)
        {
            if(!l) dp[k]=0;
            else
            {
                scanf("%d",&mx[k]);
                mi[k]=mx[k];
            }
            return;
        }
        int mid=l+r>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
        mx[k]=max(mx[k<<1],mx[k<<1|1]);
        mi[k]=min(mi[k<<1],mi[k<<1|1]);
        dp[k]=min(dp[k<<1],dp[k<<1|1]);
    }
    
    void query(int k,int l,int r,int opl,int opr)
    {
        if(l>=opl && r<=opr)
        {
            qm=max(qm,mx[k]);
            qi=min(qi,mi[k]);
            return;
        }
        int mid=l+r>>1;
        if(opl<=mid) query(k<<1,l,mid,opl,opr);
        if(opr>mid) query(k<<1|1,mid+1,r,opl,opr);
    }
    
    void change(int k,int l,int r,int pos,int x)
    {
        if(l==r)
        {
            dp[k]=x;
            return;
        }
        int mid=l+r>>1;
        if(pos<=mid) change(k<<1,l,mid,pos,x);
        else change(k<<1|1,mid+1,r,pos,x);
        dp[k]=min(dp[k<<1],dp[k<<1|1]);
    }
    
    void query2(int k,int l,int r,int opl,int opr)
    {
        if(l>=opl && r<=opr)
        {
            w=min(w,dp[k]);
            return;
        }
        int mid=l+r>>1;
        if(opl<=mid) query2(k<<1,l,mid,opl,opr);
        if(opr>mid) query2(k<<1|1,mid+1,r,opl,opr);
    }
    
    int main()
    {
        int n,s,l;
        scanf("%d%d%d",&n,&s,&l);
        build(1,0,n);
        int L,R,mid,tmp;
        for(int i=l;i<=n;++i)
        {
            L=1;
            R=i-l+1;
            tmp=-1;
            while(L<=R)
            {
                mid=L+R>>1;
                qm=-2e9;
                qi=2e9;
                query(1,0,n,mid,i);
                if(qm-qi<=s) 
                {
                    tmp=mid;
                    R=mid-1;
                }
                else L=mid+1;
            }
            if(tmp!=-1)
            {
                w=2e9;
                if(tmp-1<=i-l) query2(1,0,n,tmp-1,i-l);
                if(w!=2e9) change(1,0,n,i,w+1);
            }
        }
        w=2e9;
        query2(1,0,n,n,n);
        if(w==2e9) w=-1;
        printf("%d",w);
    }
    作者:xxy
    本文版权归作者和博客园共有,转载请用链接,请勿原文转载,Thanks♪(・ω・)ノ。
  • 相关阅读:
    Python学习-字符编码浅析
    python元组,集合类型,及字典补充
    python字符串,列表常用操作
    python流程控制
    Python之线程&进程
    yii框架的中的一些使用介绍
    《最牛B的Linux Shell命令》笔记
    CentOS6.8上安装epel
    mysql 5.7 Group Replication
    mysql5.7 参数记录 (持续更新)
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/15367034.html
Copyright © 2020-2023  润新知