zoukankan      html  css  js  c++  java
  • [SCOI 2014] 方伯伯的玉米田

    [题目链接]

              https://www.lydsy.com/JudgeOnline/problem.php?id=3594

    [算法]

            首先有一个结论 : 每次选择的区间右端点一定是n  

            根据这个结论 , 设fi,j表示前i株玉米拔高j次的最长不下降子序列长度

            则fi,j = max{fp,q + 1} (q <= j , ap + q <= ai + j)

           二维树状数组优化即可

           时间复杂度 : O(NKlogK ^ 2)

    [代码]

           

    #include<bits/stdc++.h>
    using namespace std;
    #define N 10010
    #define K 510
    #define M 5510
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    
    #define rint register int
    
    int n , k , m;
    int a[N];
    int c[K][M];
    
    template <typename T> inline void chkmin(T &x , T y) { x = min(x , y); }
    template <typename T> inline void chkmax(T &x , T y) { x = max(x , y); }
    template <typename T> inline void read(T &x)
    {
       T f = 1; x = 0;
       char c = getchar();
       for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
       for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
       x *= f;
    }
    
    inline int lowbit(int x)
    {
        return x & (-x);    
    }    
    inline void modify(int x , int y , int value)
    {
        for (rint i = x; i <= k + 1; i += lowbit(i))
        {
            for (rint j = y; j <= m; j += lowbit(j))
            {
                chkmax(c[i][j] , value);
            }
        }
    }
    inline int query(int x , int y)
    {
        int ret = 0;
        for (rint i = x; i; i -= lowbit(i))
        {
            for (rint j = y; j; j -= lowbit(j))
            {
                chkmax(ret , c[i][j]);
            }
        }
        return ret;
    }
    
    int main()
    {
       
       // f(i , j) = max{ f(p , q) + 1 } ( q <= j , ap + q <= ai + j }
       read(n); read(k);
       int mx = 0;
       for (rint i = 1; i <= n; i++) 
       {
               read(a[i]);
               chkmax(mx , a[i]);
       }
       m = k + mx + 1;
       int ans = 0;
       for (rint i = 1; i <= n; i++)
       {
               for (rint j = k; ~j; j--)
               {
                   int tmp = query(j + 1 , a[i] + j) + 1;
                   chkmax(ans , tmp);
                modify(j + 1 , a[i] + j , tmp);    
            }
       }
       printf("%d
    " , ans);
       
       return 0;
    }
  • 相关阅读:
    新式类、经典类与多继承
    实现抽象类之方式二
    实现抽象类之方式一
    re模块
    28个高频Linux命令
    Git使用教程
    编程语言介绍
    编码
    进制
    操作系统简史
  • 原文地址:https://www.cnblogs.com/evenbao/p/10360374.html
Copyright © 2011-2022 走看看