zoukankan      html  css  js  c++  java
  • 【BZOJ3594】方伯伯的玉米田(SCOI2014)-DP+二维树状数组

    测试地址:方伯伯的玉米田
    做法:本题需要用到DP+二维树状数组。
    首先,我们发现每次拔高的区间都是一个后缀。这个自己画一画就大概能证出来了。
    那么我们就有了一个状态定义:令f(i,j)为前i个后缀被拔高了j次能获得的最长不下降子序列长度,有状态转移方程:
    f(i,j)=1+max{f(p,q)|p<i,qj,apaijq}
    我们发现apaijq可以写成ap+qai+j,那么一个状态f(i,j)就有了一个二维坐标(j,ai+j),而我们要做的就是从小到大枚举i,每次状态更新时只要找到一个点左下角所有状态的最大值即可,这个显然可以用二维树状数组维护,于是我们就完成了这一题,时间复杂度为O(nklognlogk)
    以下是本人代码:

    #include <bits/stdc++.h>
    using namespace std;
    int n,k,mxx,x[10010],mx[510][6010]={0};
    
    int lowbit(int x)
    {
        return x&(-x);
    }
    
    void modify(int x,int y,int c)
    {
        for(int i=x;i<=k+1;i+=lowbit(i))
            for(int j=y;j<=mxx+k;j+=lowbit(j))
                mx[i][j]=max(mx[i][j],c);
    }
    
    int calc_max(int x,int y)
    {
        int ans=0;
        for(int i=x;i;i-=lowbit(i))
            for(int j=y;j;j-=lowbit(j))
                ans=max(ans,mx[i][j]);
        return ans;
    }
    
    int main()
    {
        scanf("%d%d",&n,&k);
        mxx=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&x[i]);
            mxx=max(mxx,x[i]);
        }
    
        for(int i=1;i<=n;i++)
            for(int j=k;j>=0;j--)
            {
                int now=calc_max(j+1,x[i]+j)+1;
                modify(j+1,x[i]+j,now);
            }
        printf("%d",calc_max(k+1,mxx+k));
    
        return 0;
    }
  • 相关阅读:
    Hadoop概论
    虚拟机
    Linux的常用命令
    jsoup抓取数据
    分享JQuery动画插件Velocity.js的六种列表加载特效
    html5和css3打造一款创意404页面
    分享一款基于jquery的圆形动画按钮
    一款基于jquery和css3实现的摩天轮式分享按钮
    一款纯css3实现的环形导航菜单
    一款纯css3实现的动画加载导航
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793374.html
Copyright © 2011-2022 走看看