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

 

posted @ 2018-10-12 11:48  sjkmost  阅读(149)  评论(0编辑  收藏  举报