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;
    }
  • 相关阅读:
    Day01-基础加强笔记
    CS Academy Round#2 E.Matrix Coloring
    AtCoder ABC198 F
    NERC2021 B. Button Lock
    AtCoder ARC115 E
    NOI Online 2021 Round 1 提高组 愤怒的小 N
    洛谷 P6918 [ICPC2016 WF]Branch Assignment
    AtCoder ARC076 F
    Atcoder ABC155 F
    POJ 1966 Cable TV Network
  • 原文地址:https://www.cnblogs.com/sjkmost/p/9769134.html
Copyright © 2011-2022 走看看