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; }