[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\n" , ans);
   
   return 0;
}

 

posted @ 2019-02-10 21:52  evenbao  阅读(163)  评论(0编辑  收藏  举报