zoukankan      html  css  js  c++  java
  • 平衡树模板

    1829. [Tyvj 1728]普通平衡树

    ★★★   输入文件:phs.in   输出文件:phs.out   简单对比
    时间限制:1 s   内存限制:128 MB

    【题目描述】

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

    【输入格式】

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

    【输出格式】

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

    【样例输入】

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

    【样例输出】

    106465
    84185
    492737

    【提示】

    1.n的数据范围:n<=100000
    2.每个数的数据范围:[-1e7,1e7]
     
    【Treap】
    cojs上测试:运行时间 0.129 s      内存使用 2.63 MiB
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 using namespace std;
     5 struct data{int l,r,v,size,fix,w;}tr[100005];
     6 int n,len,root,ans;
     7 char buf[1<<15],*fs,*ft;
     8 inline char getc() {return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;}
     9 inline int read()
    10 {
    11     int x=0,f=1;  char ch=getc();
    12     while(!isdigit(ch))  {if(ch=='-')  f=-1;  ch=getc();}
    13     while(isdigit(ch))  {x=x*10+ch-'0';  ch=getc();}
    14     return x*f;
    15 }
    16 void update(int k){tr[k].size=tr[tr[k].l].size+tr[tr[k].r].size+tr[k].w;}
    17 void rturn(int &k){int t=tr[k].l;tr[k].l=tr[t].r;tr[t].r=k;tr[t].size=tr[k].size;update(k);k=t;}
    18 void lturn(int &k){int t=tr[k].r;tr[k].r=tr[t].l;tr[t].l=k;tr[t].size=tr[k].size;update(k);k=t;}
    19 void insert(int &k,int x)
    20 {
    21     if(k==0){len++;k=len;tr[k].size=tr[k].w=1;tr[k].v=x;tr[k].fix=rand();return;}
    22     tr[k].size++;
    23     if(tr[k].v==x)tr[k].w++;//每个结点顺便记录下与该节点相同值的数的个数
    24     else if(x>tr[k].v){insert(tr[k].r,x);if(tr[tr[k].r].fix<tr[k].fix)lturn(k);}
    25     else {insert(tr[k].l,x);if(tr[tr[k].l].fix<tr[k].fix)rturn(k);} 
    26 }
    27 void del(int &k,int x)
    28 {
    29     if(k==0)return; 
    30     if(tr[k].v==x)
    31     {
    32         if(tr[k].w>1){tr[k].w--;tr[k].size--;return;}
    33         if(tr[k].l*tr[k].r==0)k=tr[k].l+tr[k].r;//有一个儿子为空
    34         else if(tr[tr[k].l].fix<tr[tr[k].r].fix) rturn(k),del(k,x);
    35         else lturn(k),del(k,x);
    36     }
    37     else if(x>tr[k].v) tr[k].size--,del(tr[k].r,x);
    38     else tr[k].size--,del(tr[k].l,x);
    39 }
    40 int rank(int k,int x)
    41 {
    42     if(k==0) return 0;
    43     if(tr[k].v==x) return tr[tr[k].l].size+1;
    44     else if(x>tr[k].v) return tr[tr[k].l].size+tr[k].w+rank(tr[k].r,x);
    45     else return rank(tr[k].l,x);
    46 }
    47 int Findkth(int k,int x)
    48 {
    49     if(k==0)return 0;
    50     if(x<=tr[tr[k].l].size) return Findkth(tr[k].l,x);
    51     else if(x>tr[tr[k].l].size+tr[k].w) return Findkth(tr[k].r,x-tr[tr[k].l].size-tr[k].w);
    52     else return tr[k].v;
    53 }
    54 void get_before(int k,int x)
    55 {
    56     if(k==0)return;
    57     if(tr[k].v<x) ans=k;get_before(tr[k].r,x);
    58     else get_before(tr[k].l,x);
    59 }
    60 void get_behind(int k,int x)
    61 {
    62     if(k==0)return;
    63     if(tr[k].v>x) ans=k;get_behind(tr[k].l,x);
    64     else get_behind(tr[k].r,x);
    65 }
    66 int main()
    67 {
    68     freopen("phs.in","r",stdin);
    69     freopen("phs.out","w",stdout);
    70     n=read();
    71     int flag,x;
    72     for(int i=1;i<=n;i++)
    73     {
    74         flag=read();  x=read();
    75         switch(flag)
    76         {
    77             case 1:insert(root,x);break;
    78             case 2:del(root,x);break;
    79             case 3:printf("%d
    ",rank(root,x));break;
    80             case 4:printf("%d
    ",Findkth(root,x));break;
    81             case 5:ans=0;get_before(root,x);printf("%d
    ",tr[ans].v);break;
    82             case 6:ans=0;get_behind(root,x);printf("%d
    ",tr[ans].v);break;
    83         }
    84     }
    85     return 0;
    86 }

    【替罪羊树】

    cojs上测试:运行时间 0.180 s     内存使用 2.63 MiB

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cstdlib>
      5 #include<cmath>
      6 #include<ctime>
      7 #include<algorithm>
      8 using namespace std;
      9 #define INF 1000000000
     10 const double chty=0.75;  //平衡常数
     11 struct node{int son[2],f,size,v;}tr[100005];
     12 int n,len,root,top,stack[100005];
     13 char buf[1<<15],*fs,*ft;
     14 inline char getc() {return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;}
     15 inline int read()
     16 {
     17     int x=0,f=1;  char ch=getc();
     18     while(!isdigit(ch))  {if(ch=='-')  f=-1;  ch=getc();}
     19     while(isdigit(ch))  {x=x*10+ch-'0';  ch=getc();}
     20     return x*f;
     21 }
     22 void init()
     23 {
     24     len=2;  root=1;
     25     tr[1].size=2;  tr[1].v=-INF;  tr[1].son[1]=2;
     26     tr[2].size=1;  tr[2].v=INF;   tr[2].f=1;
     27 }
     28 bool balance(int x) 
     29 {
     30     double p=tr[x].size*chty;
     31     return p>=(double)tr[tr[x].son[0]].size&&p>=(double)tr[tr[x].son[1]].size;
     32 }
     33 void dfs(int x)//中序遍历
     34 {
     35     if(!x)  return;
     36     dfs(tr[x].son[0]);
     37     stack[++top]=x;
     38     dfs(tr[x].son[1]);
     39 }
     40 int build(int l,int r)
     41 {
     42     if(l>r)  return 0;
     43     int mid=(l+r)/2,x=stack[mid];
     44     tr[tr[x].son[0]=build(l,mid-1)].f=x;
     45     tr[tr[x].son[1]=build(mid+1,r)].f=x;
     46     tr[x].size=tr[tr[x].son[0]].size+tr[tr[x].son[1]].size+1;
     47     return x;
     48 }
     49 void rebuild(int x)
     50 {
     51     top=0;  dfs(x);
     52     int fa=tr[x].f,which=(tr[fa].son[1]==x);
     53     int sonroot=build(1,top);
     54     tr[tr[fa].son[which]=sonroot].f=fa;
     55     if(x==root)  root=sonroot;
     56 }
     57 int find(int v)
     58 {
     59     int now=root;
     60     while(now)
     61     {
     62         if(v==tr[now].v)  return now;
     63         else now=tr[now].son[v>tr[now].v];
     64     }
     65 }
     66 void insert(int v)
     67 {
     68     int now=root,p=++len; 
     69     tr[p].v=v;  tr[p].size=1;//新开结点
     70     while(1)
     71     {
     72         tr[now].size++;
     73         int which=(v>=tr[now].v);//表示p在当前根的哪个子树内
     74         if(tr[now].son[which])  now=tr[now].son[which];  
     75         else {tr[tr[now].son[which]=p].f=now;  break;}
     76     }
     77     int id=0;
     78     for(int i=p;i;i=tr[i].f)  if(!balance(i))  id=i;//记录不平衡点
     79     if(id)  rebuild(id);//重构子树
     80 }
     81 void del(int x)
     82 {
     83     if(tr[x].son[0]&&tr[x].son[1])
     84     {
     85         int p=tr[x].son[0];
     86         while(tr[p].son[1])  p=tr[p].son[1];
     87         tr[x].v=tr[p].v;  x=p;
     88     }
     89     int Son=(tr[x].son[0])?tr[x].son[0]:tr[x].son[1],which=(tr[tr[x].f].son[1]==x);
     90     tr[tr[tr[x].f].son[which]=Son].f=tr[x].f;
     91     for(int i=tr[x].f;i;i=tr[i].f)  tr[i].size--;
     92     if(x==root)  root=Son;
     93 }
     94 int rank(int v)
     95 {
     96     int now=root,ans=0;
     97     while(now)
     98     {
     99         if(tr[now].v<v)  {ans+=tr[tr[now].son[0]].size+1;  now=tr[now].son[1];}
    100         else now=tr[now].son[0];
    101     }
    102     return ans;
    103 }
    104 int kth(int x)
    105 {
    106     int now=root;
    107     while(1)
    108     {
    109         if(tr[tr[now].son[0]].size==x-1)  return now;
    110         else if(tr[tr[now].son[0]].size>=x)  now=tr[now].son[0];
    111         else x-=tr[tr[now].son[0]].size+1,now=tr[now].son[1];
    112     }
    113     return now;
    114 }
    115 int before(int v)
    116 {
    117     int now=root,ans=-INF;
    118     while(now)
    119     {
    120         if(tr[now].v<v)  ans=max(ans,tr[now].v),now=tr[now].son[1];
    121         else now=tr[now].son[0];
    122     }
    123     return ans;
    124 }
    125 int after(int v)
    126 {
    127     int now=root,ans=INF;
    128     while(now)
    129     {
    130         if(tr[now].v>v)  ans=min(ans,tr[now].v),now=tr[now].son[0];
    131         else now=tr[now].son[1];
    132     }
    133     return ans;
    134 }
    135 int main()
    136 {
    137     freopen("phs.in","r",stdin);
    138     freopen("phs.out","w",stdout);
    139     init();
    140     n=read();
    141     for(int i=1;i<=n;i++)
    142     {
    143         int flag=read(),x=read();
    144         if(flag==1)  insert(x);
    145         if(flag==2)  del(find(x));
    146         if(flag==3)  printf("%d
    ",rank(x));
    147         if(flag==4)  printf("%d
    ",tr[kth(x+1)].v);
    148         if(flag==5)  printf("%d
    ",before(x));
    149         if(flag==6)  printf("%d
    ",after(x));
    150     }
    151     return 0;
    152 }

    不论从代码长度,还是实测时间上 ,显然Treap比较优

    大力支持使用Treap

    然而据说SBT比Treap的实测时间要优

    有空学学 

     
     
  • 相关阅读:
    axios核心技术---1.HTTP相关
    Leetcode刷题
    Java入门13---Optional处理null对象
    Java入门12---Stream
    谈谈前后端分离及认证选择
    react监控props的变化
    如何使用懒加载
    CSS文字超出省略
    React的slot插槽
    React 的函数组件和类组件中的props
  • 原文地址:https://www.cnblogs.com/chty/p/5938179.html
Copyright © 2011-2022 走看看