• 【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;
    }
  • 相关阅读:
    How to alter department in PMS system
    Can't create new folder in windows7
    calculate fraction by oracle
    Long Wei information technology development Limited by Share Ltd interview summary.
    ORACLE BACKUP AND RECOVERY
    DESCRIBE:When you mouse click right-side is open an application and click left-side is attribution.
    ORACLE_TO_CHAR Function
    电脑BOIS设置
    JSP点击表头排序
    jsp+js实现可排序表格
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793374.html
Copyright © 2020-2023  润新知