zoukankan      html  css  js  c++  java
  • BZOJ 3173

    将一个长为n的排列从小到大插入序列中,问每次插入后的LIS长度。

    $$n leq 10^5$$

    因为是从小到大,所以以新插入的数结尾的LIS长度必然是它前面的最大LIS长度+1,随便用一个数据结构维护即可,我用的splay。

    const int MAXN = 100000 + 5;
    
    struct Splay {
      struct Node {
        Node *ch[2];
        int sz, val, max;
        
    #define _sz(x) ((x) ? (x)->sz : 0)
    #define _max(x) ((x) ? (x)->max : 0)
        void push_up() {
          sz = _sz(ch[0]) + 1 + _sz(ch[1]);
          max = mymax(val, mymax(_max(ch[0]), _max(ch[1])));
        }
        
        int comp(int &k) {
          return k == _sz(ch[0]) + 1 ? -1 : (k > _sz(ch[0]) + 1 && (k -= _sz(ch[0]) + 1));
        }
      } nd[MAXN * 2], *pos, *root;
      
      Splay() {
        pos = nd;
        root = NULL;
      }
      
      Node *new_node(int x) {
        pos->ch[0] = pos->ch[1] = NULL;
        pos->sz = 1;
        pos->val = pos->max = x;
        return pos ++;
      }
      
      void rotate(Node *&o, int d) {
        Node *p = o->ch[d ^ 1];
        o->ch[d ^ 1] = p->ch[d];
        p->ch[d] = o;
        o->push_up();
        p->push_up();
        o = p;
      }
      
      void splay(Node *&o, int k) {
        int d1 = o->comp(k);
        if (d1 != -1 && o->ch[d1]) {
          int d2 = o->ch[d1]->comp(k);
          if (d2 != -1 && o->ch[d1]->ch[d2]) {
            splay(o->ch[d1]->ch[d2], k);
            if (d1 == d2)
              rotate(o, d2 ^ 1), rotate(o, d1 ^ 1);
            else
              rotate(o->ch[d1], d2 ^ 1), rotate(o, d1 ^ 1);
          } else
            rotate(o, d1 ^ 1);
        }
      }
      
      Node *split(Node *&o, int k, int d) {
        if (!o)
          return NULL;
        splay(o, k);
        Node *p = o->ch[d];
        o->ch[d] = NULL;
        o->push_up();
        return p;
      }
      
      void merge(Node *&o, Node *&p) {
        if (!o)
          std::swap(o, p);
        splay(o, INF);
        o->ch[1] = p;
        o->push_up();
        p = NULL;
      }
      
      int query(Node *&o, int k) {
        if (!k)
          return 0;
        Node *p = split(o, k, 1);
        int ans = o->max;
        merge(o, p);
        return ans;
      }
      
      void insert(Node *&o, int k, int x) {
        Node *p = new_node(x);
        if (!k) {
          merge(p, o);
          o = p;
          return;
        }
        Node *q = split(o, k, 1);
        merge(o, p);
        merge(o, q);
      }
    } T;
    
    int main() {
      int n;
      scanf("%d", &n);
      int ans = 0;
      For(i, 1, n) {
        int x;
        scanf("%d", &x);
        int len = T.query(T.root, x) + 1;
        chkmax(ans, len);
        T.insert(T.root, x, len);
        printf("%d
    ", ans);
      }
      return 0;
    }
  • 相关阅读:
    async和await是如何实现异步编程?
    HD-ACM算法专攻系列(23)——Crixalis's Equipment
    HD-ACM算法专攻系列(22)——Max Sum
    HD-ACM算法专攻系列(21)——Wooden Sticks
    HD-ACM算法专攻系列(20)——七夕节
    HD-ACM算法专攻系列(19)——Leftmost Digit
    搭建Prometheus平台,你必须考虑的6个因素
    实用教程丨使用K3s和MySQL运行Rancher 2.4
    Kubernetes Ingress简单入门
    一文讲透Cluster API的前世、今生与未来
  • 原文地址:https://www.cnblogs.com/sjkmost/p/9777327.html
Copyright © 2011-2022 走看看