【BZOJ3682】Phorni

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_39972971/article/details/82429301

【题目链接】

【思路要点】

  • 利用 T r e a p 对新产生的后缀动态标号,维护一棵后缀平衡树,再用线段树支持修改即可。
  • 时间复杂度 O ( M L o g N + M L o g M + N )

【代码】


#include<bits/stdc++.h>

using namespace std;
const int MAXN = 5e5 + 5;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); } 
template <typename T> void read(T &x) {
  x = 0; int f = 1;
  char c = getchar();
  for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
  for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
  x *= f;
}
template <typename T> void write(T x) {
  if (x < 0) x = -x, putchar('-');
  if (x > 9) write(x / 10);
  putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {
  write(x);
  puts("");
}
struct Treap {
  struct Node {
      ull val, var;
      unsigned weight;
      int child[2], father;
  } a[MAXN];
  int root, n;
  unsigned seed;
  char s[MAXN];
  bool labeled[MAXN];
  unsigned Rand() {
      seed = seed * seed + rand();
      return seed;
  }
  bool cmp(int x, int y) {
      if (x == y) return false;
      if (x == 0) return true;
      if (y == 0) return false;
      if (labeled[x] && labeled[y]) return a[x].val + a[x].var < a[y].val + a[y].var;
      else {
          if (s[x] == s[y]) return cmp(x - 1, y - 1);
          else return s[x] < s[y];
      }
  }
  bool get(int pos) {
      return pos == a[a[pos].father].child[1];
  }
  void rotate(int x) {
      int f = a[x].father, g = a[f].father;
      bool tmp = get(x);
      a[x].father = g;
      if (g) a[g].child[get(f)] = x;
      a[f].child[tmp] = a[x].child[tmp ^ 1];
      a[a[x].child[tmp ^ 1]].father = f;
      a[f].father = x;
      a[x].child[tmp ^ 1] = f;
      if (g == 0) root = x;
  }
  void label(int &root, int pos, int f) {
      if (root == 0) {
          root = pos;
          a[pos].father = f;
          return;
      }
      if (cmp(pos, root)) {
          label(a[root].child[0], pos, root);
          if (a[a[root].child[0]].weight < a[root].weight) rotate(a[root].child[0]);
      } else {
          label(a[root].child[1], pos, root);
          if (a[a[root].child[1]].weight < a[root].weight) rotate(a[root].child[1]);
      }
  }
  void dfs(int pos) {
      ull mid = (a[pos].val + a[pos].var) / 2;
      if (a[pos].child[0]) {
          a[a[pos].child[0]].val = a[pos].val;
          a[a[pos].child[0]].var = mid - 1;
          dfs(a[pos].child[0]);
      }
      if (a[pos].child[1]) {
          a[a[pos].child[1]].val = mid + 1;
          a[a[pos].child[1]].var = a[pos].var;
          dfs(a[pos].child[1]);
      }
  }
  void label(int pos) {
      a[pos].weight = Rand();
      label(root, pos, 0);
      labeled[pos] = true;
      if (pos == root) a[root].val = 0, a[root].var = 1ull << 63;
      else {
          int f = a[pos].father;
          ull tmp = (a[f].val + a[f].var) / 2;
          if (get(pos)) a[pos].var = a[f].var, a[pos].val = tmp + 1;
          else a[pos].val = a[f].val, a[pos].var = tmp - 1;
      }
      dfs(pos);
  }
  void insert(char c) {
      s[++n] = c;
      label(n);
  }
  void init(int len) {
      root = 1, seed = 1, n = len;
      labeled[root] = true;
      a[root].weight = Rand();
      a[root].val = 0, a[root].var = 1ull << 63;
      scanf("\n%s", s + 1);
      reverse(s + 1, s + len + 1);
      for (int i = 2; i <= n; i++)
          label(i);
  }
} Treap;
char s[MAXN];
int n, m, len, type, p[MAXN];
struct SegmentTree {
  struct Node {
      int lc, rc;
      int home;
  } a[MAXN * 2];
  int n, root, size;
  void update(int root) {
      if (Treap.cmp(p[a[a[root].rc].home], p[a[a[root].lc].home])) a[root].home = a[a[root].rc].home;
      else a[root].home = a[a[root].lc].home;
  }
  void build(int &root, int l, int r) {
      root = ++size;
      if (l == r) {
          a[root].home = l;
          return;
      }
      int mid = (l + r) / 2;
      build(a[root].lc, l, mid);
      build(a[root].rc, mid + 1, r);
      update(root);
  }
  void init(int x) {
      n = x;
      root = size = 0;
      build(root, 1, n);
  }
  void modify(int root, int l, int r, int pos) {
      if (l == r) return;
      int mid = (l + r) / 2;
      if (mid >= pos) modify(a[root].lc, l, mid, pos);
      else modify(a[root].rc, mid + 1, r, pos);
      update(root);
  }
  void modify(int pos) {
      modify(root, 1, n, pos);
  }
  int query(int root, int l, int r, int ql, int qr) {
      if (l == ql && r == qr) return a[root].home;
      int mid = (l + r) / 2;
      if (mid >= qr) return query(a[root].lc, l, mid, ql, qr);
      else if (mid + 1 <= ql) return query(a[root].rc, mid + 1, r, ql, qr);
      else {
          int tmp = query(a[root].lc, l, mid, ql, mid);
          int tnp = query(a[root].rc, mid + 1, r, mid + 1, qr);
          if (Treap.cmp(p[tnp], p[tmp])) return tnp;
          else return tmp;
      }
  }
  int query(int l, int r) {
      return query(root, 1, n, l, r);
  }
} ST;
char getopt() {
  char ch = getchar();
  while (ch != 'C' && ch != 'Q' && ch != 'I') ch = getchar();
  return ch; 
}
int main() {
  read(n), read(m), read(len), read(type);
  Treap.init(len);
  int lastans = 0;
  for (int i = 1; i <= n; i++)
      read(p[i]);
  ST.init(n);
  for (int i = 1; i <= m; i++) {
      char opt = getopt();
      if (opt == 'I') {
          int tmp; read(tmp);
          tmp ^= lastans * type;
          Treap.insert(tmp + 'a');
      }
      if (opt == 'C') {
          int pos; read(pos);
          read(p[pos]);
          ST.modify(pos);
      }
      if (opt == 'Q') {
          int l, r; read(l), read(r);
          printf("%d\n", lastans = ST.query(l, r));
      }
  }
  return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39972971/article/details/82429301