[Codeforces809D] Hitchhiking in the Baltic States

给定 (n) 个区间 ([l_i,r_i]) ,整数序列 ({a_n}) 满足 (a_i in [l_i, r_i]),求该序列的最长严格上升子序列的最大长度。

(1 leq n leq 3 imes 10^5, 1 leq l_i leq r_i leq 10^9)

(dp[i][j]) 表示在前 (i) 个数中选择一个长度为 (j)LIS,子序列末尾那个数最小是多少。

由于是严格上升,不难发现 (dp[i][0] < dp[i][1] < dp[i][2] < cdots < dp[i][n])

忽略第一维,当序列末尾加入一个区间为 ([l,r]) 的数时,分类讨论:

  • 对于满足 (dp[j] < l) 最大的 (j),当前数选择 (l) ,可以用 (l) 更新 (j + 1)
  • 对于 (l leq dp[j] < r),当前数选择 (dp[j] + 1) 就可以更新 (dp[j + 1]),由于单调性,(dp[j] + 1 leq dp[j + 1]),一定可以更新,所以相当于将这段整体右移一位再整体加一。

由于单调性,这个操作可以用平衡树维护。

#include <bits/stdc++.h>
#define dbg(args...) std::cerr << "33[31;1m" << #args << " -> ", err(args)
inline void err() { std::cerr << "33[0m
"; }
template<class T, class... U>
inline void err(const T &x, const U &... a) { std::cerr << x << ' '; err(a...); }

constexpr int N(3e5 + 5), INF(1e9 + 1);

struct Node {
  Node *ls, *rs;
  int siz, rnd, val, tag;
  inline void pushup() { siz = ls->siz + rs->siz + 1; }
  inline void add(int);
  inline void pushdown() { if (tag) ls->add(tag), rs->add(tag), tag = 0; }
} t[N], *null = new Node();
void Node::add(int x) { if (this != null) tag += x, val += x; }
void split_v(Node *o, int v, Node *&x, Node *&y) {
  if (o == null) {
    x = y = null; return;
  }
  o->pushdown();
  if (v < o->val)
    y = o, split_v(o->ls, v, x, o->ls);
  else
    x = o, split_v(o->rs, v, o->rs, y);
  o->pushup();
}
void split_k(Node *o, int k, Node *&x, Node *&y) {
  if (o == null) {
    x = y = null; return;
  }
  o->pushdown();
  if (k <= o->ls->siz)
    y = o, split_k(o->ls, k, x, o->ls);
  else
    x = o, split_k(o->rs, k - o->ls->siz - 1, o->rs, y);
  o->pushup();
}
Node* merge(Node *x, Node *y) {
  if (x == null) return y;
  if (y == null) return x;
  x->pushdown(), y->pushdown();
  return x->rnd < y->rnd
    ? (x->rs = merge(x->rs, y), x->pushup(), x)
    : (y->ls = merge(x, y->ls), y->pushup(), y);
}
int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  int n; std::cin >> n;
  null->ls = null->rs = null, null->siz = 0, null->val = INF;
  Node *root = null;
  for (int i = 0; i <= n; i++) {
    static std::mt19937 gen(std::chrono::high_resolution_clock().now().time_since_epoch().count());
    t[i].ls = t[i].rs = null;
    t[i].siz = 1, t[i].rnd = gen();
    t[i].val = i ? INF : 0;
    root = merge(root, t + i);
  }
  while (n--) {
    int l, r; std::cin >> l >> r;
    if (l > r) continue;
    Node *a, *b, *c, *d, *o;
    split_v(root, l - 1, a, b);
    split_v(b, r - 1, b, d);
    if (b == null) {
      for (o = d; o->ls != null; o = o->ls) o->pushdown();
      o->val = l;
      root = merge(a, d);
    } else {
      split_k(b, b->siz - 1, b, c);
      for (o = d; o->ls != null; o = o->ls) o->pushdown();
      o->val = std::min(o->val, c->val + 1);
      for (o = b; o->ls != null; o = o->ls) o->pushdown();
      c->val = std::min(l, o->val);
      b->add(1);
      root = merge(merge(a, c), merge(b, d));
    }
  }
  Node *a, *b;
  split_v(root, INF - 1, a, b);
  std::cout << a->siz - 1 << "
";
  return 0;
}
原文地址:https://www.cnblogs.com/HolyK/p/14149054.html