BZOJ3224普通平衡树

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

3224: Tyvj 1728 普通平衡树
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 6588 Solved: 2722
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
平衡树
treap模板题。。
附上本蒟蒻的代码:

#include<cstdio>
#include<iostream>
#include<cstdlib>
using namespace std;
struct data
{
    int l,r,v,size,rnd,w;
}node[100001];
int n,size,root,ans;

int read()
{
    int w=0,c=1; char ch=getchar();
    while (ch<'0' || ch>'9')
      {
        if (ch=='-') c=-1;
        ch=getchar();
      }
    while (ch>='0' && ch<='9')
      w=w*10+ch-'0',ch=getchar();
    return w*c;
}

void update(int s)
{
    node[s].size=node[node[s].l].size+node[node[s].r].size+node[s].w;
}

void rturn(int &s)
{
    int t=node[s].l;
    node[s].l=node[t].r,node[t].r=s,node[t].size=node[s].size,update(s),s=t;
}

void lturn(int &s)
{
    int t=node[s].r;
    node[s].r=node[t].l,node[t].l=s,node[t].size=node[s].size,update(s),s=t;
}

void insert(int &s,int x)
{
    if (!s) {size++,s=size,node[s].size=node[s].w=1,node[s].v=x,node[s].rnd=rand();return;}
    node[s].size++;
    if (node[s].v==x) 
      node[s].w++;
    else 
      if (x>node[s].v)
        {
            insert(node[s].r,x);
            if (node[node[s].r].rnd<node[s].rnd) lturn(s);
        }
      else
        {
            insert(node[s].l,x);
            if (node[node[s].l].rnd<node[s].rnd) rturn(s);
        }
}

void del(int &s,int x)
{
    if (!s) return;
    if (node[s].v==x)
      {
        if (node[s].w>1) {node[s].w--,node[s].size--;return;}
        if (node[s].l*node[s].r==0) s=node[s].l+node[s].r;
        else if (node[node[s].l].rnd<node[node[s].r].rnd) rturn(s),del(s,x);
        else lturn(s),del(s,x);
      }
    else if (x>node[s].v) node[s].size--,del(node[s].r,x);
    else node[s].size--,del(node[s].l,x);
}

int queryrank(int s,int x)
{
    if (!s) return 0;
    if (node[s].v==x) return node[node[s].l].size+1;
    else if (x>node[s].v) return node[node[s].l].size+node[s].w+queryrank(node[s].r,x);
    else return queryrank(node[s].l,x);
}

int querynum(int s,int x)
{
    if (!s) return 0;
    if (x<=node[node[s].l].size) return querynum(node[s].l,x);
    else if (x>node[node[s].l].size+node[s].w) return querynum(node[s].r,x-node[node[s].l].size-node[s].w);
    else return node[s].v;
}

void querypred(int s,int x)
{
    if (!s) return;
    if (node[s].v<x) ans=s,querypred(node[s].r,x);
    else querypred(node[s].l,x);
}

void querysucc(int s,int x)
{
    if (!s) return;
    if (node[s].v>x) ans=s,querysucc(node[s].l,x);
    else querysucc(node[s].r,x); 
}

int main()
{
    int p,x,i;
    n=read();
    for (i=1;i<=n;i++)
      {
        p=read(),x=read();
        switch (p)
          {
            case 1:insert(root,x);break;
            case 2:del(root,x);break;
            case 3:printf("%d\n",queryrank(root,x));break;
            case 4:printf("%d\n",querynum(root,x));break;
            case 5:ans=0;querypred(root,x);printf("%d\n",node[ans].v);break;
            case 6:ans=0;querysucc(root,x);printf("%d\n",node[ans].v);break;
          }
      }
    return 0;
}
展开阅读全文

没有更多推荐了,返回首页