BZOJ 题目3224: Tyvj 1728 普通平衡树(SBT)

3224: Tyvj 1728 普通平衡树

Time Limit: 10 Sec  Memory Limit: 128 MB

Submit: 4350  Solved: 1769

[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.每个数的数据范围:[-1e7,1e7]

Source

平衡树

好吧,,从昨天就一直改这个代码,,,右旋的时候size少加了1,,,re一片啊,主要这个是有重的。

ac代码

/**************************************************************
    Problem: 3224
    User: kxh1995
    Language: C++
    Result: Accepted
    Time:484 ms
    Memory:47708 kb
****************************************************************/

#include<stdio.h>
#include<string.h>
#define min(a,b) (a>b?b:a)
#define INF 0xfffffff
struct s
{
    int key,left,right,size,sc,cnt;
}tree[2001000];
int top,root;
void left_rot(int &x)
{
    int y=tree[x].right;
    tree[x].right=tree[y].left;
    tree[y].left=x;
    tree[y].size=tree[x].size;
    tree[y].sc=tree[x].sc;
    tree[x].size=tree[tree[x].left].size+tree[tree[x].right].size+1;
    tree[x].sc=tree[tree[x].left].sc+tree[tree[x].right].sc+tree[x].cnt;
    x=y;
}
void right_rot(int &x)
{
    int y=tree[x].left;
    tree[x].left=tree[y].right;
    tree[y].right=x;
    tree[y].size=tree[x].size;
    tree[y].sc=tree[x].sc;
    tree[x].size=tree[tree[x].left].size+tree[tree[x].right].size+1;
    tree[x].sc=tree[tree[x].left].sc+tree[tree[x].right].sc+tree[x].cnt;
    x=y;
}
void maintain(int &x,bool flag)
{
    tree[x].size=tree[tree[x].left].size+tree[tree[x].right].size+1;
    tree[x].sc=tree[tree[x].left].sc+tree[tree[x].right].sc+tree[x].cnt;
    if(flag==false)
    {
        if(tree[tree[tree[x].left].left].size>tree[tree[x].right].size)
            right_rot(x);
        else
            if(tree[tree[tree[x].left].right].size>tree[tree[x].right].size)
            {
                left_rot(tree[x].left);
                right_rot(x);
            }
            else
                return;
    }
    else
    {
        if(tree[tree[tree[x].right].right].size>tree[tree[x].left].size)
            left_rot(x);
        else
            if(tree[tree[tree[x].right].left].size>tree[tree[x].left].size)
            {
                right_rot(tree[x].right);
                left_rot(x);
            }
            else
                return;
    }
    maintain(tree[x].left,false);
    maintain(tree[x].right,true);
    maintain(x,true);
    maintain(x,false);
}
void insert(int &x,int key)
{
    if(x==0)
    {
        x=++top;
    //  tree[x].left=0;
      //  tree[x].right=0;
        tree[x].size=tree[x].sc=tree[x].cnt=1;
        tree[x].key=key;
    }
    else
    {
       // tree[x].size++;
        if(tree[x].key==key)
        {
            tree[x].cnt++;
            tree[x].sc++;
        }
        else
            if(key<tree[x].key)
            {
                insert(tree[x].left,key);
                maintain(x,false);
            }
            else
            {
                insert(tree[x].right,key);
                maintain(x,true);
            }
        maintain(x,key>=tree[x].key);
    }
}
void remove(int &x,int key)
{
    if(tree[x].key==key)
    {
        if(tree[x].cnt>1)
        {
            tree[x].cnt--;
            tree[x].sc--;
        }
        else
            if(!tree[x].left&&!tree[x].right)
            {
                x=0;
            }
            else
                if(!(tree[x].left*tree[x].right))
                    x=tree[x].left+tree[x].right;
                else
                    if(tree[tree[x].left].size>tree[tree[x].right].size)
                    {
                        right_rot(x);
                        remove(tree[x].right,key);
                        maintain(x,false);
                    }
                    else
                    {
                        left_rot(x);
                        remove(tree[x].left,key);
                        maintain(x,true);
                    }
    }
    else
        if(key<tree[x].key)
        {
            remove(tree[x].left,key);
            maintain(x,true);
        }
        else
        {
            remove(tree[x].right,key);
            maintain(x,false);
        }
}
int getmin(int x)
{
    while(tree[x].left)
        x=tree[x].left;
    return tree[x].key;
}
int getmax(int x)
{
    while(tree[x].right)
        x=tree[x].right;
    return tree[x].key;
}
int pred(int &x,int y,int key)
{
    if(x==0)
    {
        return tree[y].key;
    }
    if(key>tree[x].key)
        return pred(tree[x].right,x,key);
    else
        return pred(tree[x].left,y,key);
}
int succ(int &x,int y,int key)
{
    if(x==0)
    {
        return tree[y].key;
    }
    if(key<tree[x].key)
        return succ(tree[x].left,x,key);
    else
        return succ(tree[x].right,y,key);
}
int get_min_k(int &x,int k)//选第k小的数
{
    if(tree[tree[x].left].sc<k&&k<=tree[tree[x].left].sc+tree[x].cnt)
        return tree[x].key;
    if(k<=tree[tree[x].left].sc)
        return get_min_k(tree[x].left,k);
    else
        return get_min_k(tree[x].right,k-tree[tree[x].left].sc-tree[x].cnt);
}
int rank(int &x,int key)//key排第几
{
    if(key<tree[x].key)
    {
        return rank(tree[x].left,key);
    }
    else
        if(key>tree[x].key)
            return rank(tree[x].right,key)+tree[tree[x].left].sc+tree[x].cnt;
        else
            return tree[tree[x].left].sc+1;
}
int main()
{
    int n,m;
    while(scanf("%d",&n)!=EOF)
    {
        int i;
        top=root=0;
        while(n--)
        {
            int op,x;
            scanf("%d%d",&op,&x);
            if(op==1)
                insert(root,x);
            else
                if(op==2)
                {
                    remove(root,x);
                }
                else
                    if(op==3)
                    {
                        printf("%d\n",rank(root,x));
                    }
                    else
                        if(op==4)
                        {
                            printf("%d\n",get_min_k(root,x));
                        }
                        else
                            if(op==5)
                            {
                                printf("%d\n",pred(root,0,x));
                            }
                            else
                                printf("%d\n",succ(root,0,x));
        }
    }
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-12 20:09:58

BZOJ 题目3224: Tyvj 1728 普通平衡树(SBT)的相关文章

bzoj 3224: Tyvj 1728 普通平衡树.

3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 15114  Solved: 6570[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. 求x的前驱(前驱定义为

BZOJ 3224: Tyvj 1728 普通平衡树 treap

3224: Tyvj 1728 普通平衡树 Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. 求x的前驱(前驱定义为小于x,且最大的数)6. 求x的后继(后继定义为大于x,且最小的数) Input 第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)

BZOJ 3224: Tyvj 1728 普通平衡树(BST)

treap,算是模板题了...我中间还一次交错题... -------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<cstdlib> #define rep(i,n) for(int i=0;i<n;

3224: Tyvj 1728 普通平衡树

3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2566  Solved: 1031[Submit][Status] Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. 求x的前驱(前驱定义为小于x,且最大的数)

3224: Tyvj 1728 普通平衡树(新板子)

3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 17048  Solved: 7429[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. 求x的前驱(前驱定义为

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

题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=3224 思路: splay树模板题: 推荐博客:https://blog.csdn.net/clove_unique/article/details/50630280 b站上splay树的讲解视频也可以看下,讲的很好,推荐看完视频了解了splay的原理再写 实现代码: #include<bits/stdc++.h> using namespace std; #define ll lo

BZOJ 3224 Tyvj 1728 普通平衡树 | Splay 板子

下面给出Splay的实现方法(复杂度证明什么的知道是 nlogn 就可以啦) 首先对于一颗可爱的二叉查找树,是不能保证最坏nlogn的复杂度(可以想象把一个升序序列插入) 所以我们需要一些非常巧妙的旋转操作 1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<cmath> 5 #define N 100010 6 #define which(x) (ls[fa[(x)

[bzoj] 3224 Tyvj 1728 普通平衡树 || 平衡树板子题

#!/bin/bash g++ make.cpp -o make -Wall g++ 1.cpp -o ac -Wall g++ sb.cpp -o sb -Wall while true; do ./make > 1.in ./ac < 1.in > 1.out ./sb < 1.in > sb.out if diff 1.out sb.out; then printf "AC!" else exit fi done 原文地址:https://www.c

HYSBZ 3224 Tyvj 1728 普通平衡树 splay模版

先学了splay写的 以后有空再学treap和sbt版 参考: http://blog.csdn.net/clove_unique/article/details/50630280 #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<algorithm> #include<vector>