[代码] bzoj 3224 普通平衡树(无旋treap)

Posted Anding

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[代码] bzoj 3224 普通平衡树(无旋treap)相关的知识,希望对你有一定的参考价值。

- 传送门 -

 http://www.lydsy.com/JudgeOnline/problem.php?id=3224
 

3224: Tyvj 1728 普通平衡树

Time Limit:?10 Sec??Memory Limit:?128 MB
Submit:?17311??Solved:?7553

Description

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)

Input

第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)

Output

对于操作3,4,5,6每行输出一个数,表示对应答案

Sample Input

10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598

Sample Output

106465
84185
492737

HINT

1.n的数据范围:n<=100000

2.每个数的数据范围:[-2e9,2e9]
 

- 代码 -

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <ctime>
#include <cstdlib>
#define pii pair<int, int>
#define mp make_pair
using namespace std;

template <typename ty> void read(ty &x) {
  x = 0; int f = 1; char ch = getchar();
  while (ch > '9' || ch < '0') { if (ch == '-') f = -1; ch = getchar(); }
  while (ch >= '0' && ch <= '9') { x = x*10 + ch - '0'; ch = getchar(); }
  x *= f;
}
template <typename ty> ty Max(ty a, ty b) { return a > b ? a : b; }
template <typename ty> ty Min(ty a, ty b) { return a < b ? a : b; }
template <typename ty> int Chkmin(ty a, ty b) { return a > b ? a = b, 1 : 0; }
template <typename ty> int Chkmax(ty a, ty b) { return a < b ? a = b, 1 : 0; }

typedef long long LL;
typedef double db;

const int inf = 0x7fffffff;
const int N = 1e5 + 16;

int V[N], C[N][2], SZ[N], RD[N];
int n, sz, tot, root;

void pushup(int rt) { SZ[rt] = SZ[C[rt][0]] + SZ[C[rt][1]] + 1; }

int build(int val) {

  sz++;
  V[sz] = val;
  RD[sz] = rand();
  SZ[sz] = 1;
  return sz;

}

pii split(int rt, int k) {

  if (!rt) return mp(0, 0);
  pii tmp;
  if (SZ[C[rt][0]] >= k) {
    tmp = split(C[rt][0], k); C[rt][0] = tmp.second;
    pushup(rt); tmp.second = rt;
  }
  else {
    tmp = split(C[rt][1], k - SZ[C[rt][0]] - 1); C[rt][1] = tmp.first;
    pushup(rt); tmp.first = rt;
  }
  return tmp;

}

int merge(int ra, int rb) {

  if (!ra) return rb;
  if (!rb) return ra;
  if (RD[ra] < RD[rb]) {
    C[ra][1] = merge(C[ra][1], rb);
    pushup(ra); return ra;
  }
  else {
    C[rb][0] = merge(ra, C[rb][0]);
    pushup(rb); return rb;
  }

}

int getkth(int rt, int val) {

  if (!rt) return 0;
  if (V[rt] >= val) return getkth(C[rt][0], val);
  return SZ[C[rt][0]] + 1 + getkth(C[rt][1], val);

}

int findkth(int rt, int k) {

  pii a = split(root, k - 1);
  pii b = split(a.second, 1);
  int ans = b.first;
  root = merge(merge(a.first, ans), b.second);
  return ans;

}

void work1(int v) {

  int tmp = getkth(root, v);
  pii a = split(root, tmp);
  root = merge(merge(a.first, build(v)), a.second);

}

void work2(int v) {

  int tmp = getkth(root, v);
  int t = findkth(root, tmp + 1);
  if (!t || V[t] != v) return;

  pii a = split(root, tmp);
  pii b = split(a.second, 1);
  root = merge(a.first, b.second);

}

void work3(int v) { printf("%d\n", getkth(root, v) + 1); }

void work4(int v) { printf("%d\n", V[findkth(root, v)]); }

void work5(int v) { printf("%d\n", V[findkth(root, getkth(root, v))]); }

void work6(int v) { printf("%d\n", V[findkth(root, getkth(root, v + 1) + 1)]); }

int main () {

  read(n);
  while (n --) {
    int opt, v;
    read(opt); read(v);
    switch(opt) {
      case 1: { work1(v); break; }
      case 2: { work2(v); break; }
      case 3: { work3(v); break; }
      case 4: { work4(v); break; }
      case 5: { work5(v); break; }
      case 6: { work6(v); break; }
    }
  }

  return 0;

}

以上是关于[代码] bzoj 3224 普通平衡树(无旋treap)的主要内容,如果未能解决你的问题,请参考以下文章

[Bzoj3223][Tyvj1729] 文艺平衡树(splay/无旋Treap)

[bzoj3224]普通平衡树

bzoj3224普通平衡树——treap

bzoj3224: Tyvj 1728 普通平衡树(spaly)

bzoj 3224: Tyvj 1728 普通平衡树 && loj 104 普通平衡树 (splay树)

BZOJ3224: Tyvj 1728 普通平衡树