zoukankan      html  css  js  c++  java
  • BZOJ 3594

    有一个长为n的序列,你可以进行k次区间+1,求LIS。

    $$n leq 10000,k leq 500, 1 leq a_i leq 5000$$

    首先发现每次+1的区间必然是一个后缀,设f(i,j)为以第i个数结尾,+1了j次的长度,转移是显然的,用二维BIT优化转移就能过了。

    const int MAXN = 10000 + 5, MAXM = 5000 + 5, MAXK = 500 + 5;
    
    struct BinaryIndexedTree2D {
      int arr[MAXK][MAXM + MAXK], n, m;
      
    #define lowbit(x) ((x) & -(x))
      void modify(int a, int b, int x) {
        ++ a;
        for (int i = a; i <= n; i += lowbit(i))
          for (int j = b; j <= m; j += lowbit(j))
            chkmax(arr[i][j], x);
      }
      
      int query(int a, int b) {
        ++ a;
        int ans = 0;
        for (int i = a; i; i -= lowbit(i))
          for (int j = b; j; j -= lowbit(j))
            chkmax(ans, arr[i][j]);
        return ans;
      }
    } T;
    
    int a[MAXN], f[MAXK], lis[MAXN], g[MAXN];
    
    int main() {
      int n, k;
      scanf("%d%d", &n, &k);
      int max = 0;
      For(i, 1, n) {
        scanf("%d", &a[i]);
        chkmax(max, a[i]);
      }
      T.n = k + 1, T.m = max + k;
      memset(g, 63, sizeof g);
      g[0] = 0;
      int ans = 0;
      For(i, 1, n) {
        int k = std::upper_bound(g, g + n + 1, a[i]) - g;
        lis[i] = k, g[k] = a[i];
        chkmax(ans, lis[i]);
      }
      For(i, 1, n) {
        Rep(j, k, 1) {
          f[j] = T.query(j, a[i] + j) + 1;
          T.modify(j, a[i] + j, f[j]);
          chkmax(ans, f[j]);
        }
        T.modify(0, a[i], lis[i]);
      }
      printf("%d
    ", ans);
      return 0;
    }
  • 相关阅读:
    thread.md
    Linux系统编程手册_第6章_进程
    第一章.md
    开始.md
    粘滞位
    端口转发和端口映射
    virtualbox.md
    第6章.md
    JsparentNode、parentElement,childNodes、children 它们有什么区别呢?
    Sql注入防小试
  • 原文地址:https://www.cnblogs.com/sjkmost/p/9769134.html
Copyright © 2011-2022 走看看