bzoj3224普通平衡树splay

来源:互联网 发布:淘宝待揽件是什么意思 编辑:程序博客网 时间:2024/05/20 05:10

3224: Tyvj 1728 普通平衡树

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 15298  Solved: 6658
[Submit][Status][Discuss]

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]

Source

平衡树

平衡树裸题

当时打Kth的时候吧p=rs和lsize = cur + t[p].cnt打反了,调了一个小时qwq

#include<iostream>#include<cstdlib>#include<cstdio>#include<cstring>#include<algorithm>#include<map>#include<cmath>#define maxn 315050#define inf 0x7fffffff#define ls t[p].ch[0]#define rs t[p].ch[1]#define pa t[p].fusing namespace std;int read(){    char ch = getchar(); int x = 0, f = 1;    while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}    while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}    return x * f;}struct node{    int ch[2], f, cnt, size, num;    node() {ch[0] = ch[1] = f = cnt = size = num = 0;}    node(int val, int fa) {ch[0] = ch[1] = 0; f = fa; num = val; size = cnt = 1;}}t[maxn];int n, top, sz, root;int wh(int p) {return t[pa].ch[1] == p;}void update(int p) {    t[p].size = t[ls].size + t[rs].size + t[p].cnt;}void Rotate(int p) {    int f = pa, g = t[pa].f, c = wh(p);    if(g) t[g].ch[wh(f)] = p; t[p].f = g;    t[f].ch[c] = t[p].ch[c ^ 1]; if(t[f].ch[c]) t[t[f].ch[c]].f = f;    t[p].ch[c ^ 1] = f; t[f].f = p;    update(f);}void Splay(int p, int tar) {    for(;pa != tar; Rotate(p))         if(t[pa].f != tar) Rotate(wh(pa) == wh(p) ? pa : p);    update(p);    if(tar == 0) root = p;}void Ins(int p, int val) {    if(!p) {        root = p = ++sz;        t[p] = node(val, 0);        return;    }    while(p) {        ++t[p].size;        if(val == t[p].num)        {            ++t[p].cnt;            return;        }        int &y = t[p].ch[val > t[p].num];        if(!y)        {            y = ++sz;            t[y] = node(val, p);            break;        }        p = y;    }    Splay(p, 0);}int Kth(int k) {    int p = root, lsize = 0;    while(p) {        int cur = lsize + t[ls].size;        if(k > cur && k <= cur + t[p].cnt) return p;        if(k <= cur) p = ls;        else {            lsize = cur + t[p].cnt;            p = rs;        }    }    return -1;}int find(int x){    int p = root, ret = 0;    while(p) {        if(x > t[p].num)        {            ret += t[ls].size + t[p].cnt;            p = rs;        }        else        {            if(x == t[p].num) return ret + t[ls].size + 1;            else p = ls;        }    }}int find_pre(int x){    int ans = 0, p = root;    while(p) {        if(t[p].num < x) {            ans = p;            p = rs;        }        else p = ls;    }    return ans;}int find_nxt(int x){    int ans = 0, p = root;    while(p) {        if(t[p].num > x) {            ans = p;            p = ls;        }        else p = rs;    }    return ans;}void Del(int x){    int f = find_pre(x); int p = find_nxt(x);     Splay(f, 0); Splay(p, f);    if(t[ls].cnt > 1) {--t[ls].cnt; Splay(ls, 0);}    else ls = 0;}int main(){    n = read();    Ins(root, -inf); Ins(root, inf);    for(int i = 1;i <= n; ++i) {        int opt = read(), x = read();        if(opt == 1) Ins(root, x);        if(opt == 2) Del(x);        if(opt == 3) printf("%d\n", find(x) - 1);        if(opt == 4) {            int p = Kth(x + 1);            printf("%d\n", t[p].num);        }        if(opt == 5) {            int p = find_pre(x);            printf("%d\n", t[p].num);        }        if(opt == 6) {            int p = find_nxt(x);            printf("%d\n", t[p].num);        }    }    return 0;}/*201 11 12 12 11 2 1 21 31 31 41 42 22 22 32 32 42 41 11 21 35 2 */