zoukankan      html  css  js  c++  java
  • bzoj3224 普通平衡树

    bzoj3224 普通平衡树

    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]

    题解

      如题,随便用个平衡树维护即可。(我用的是Splay)

    Code

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<cmath>
      7 using namespace std;
      8 #define ll long long
      9 #define REP(i,a,b) for(register int i=(a),_end_=(b);i<=_end_;i++)
     10 #define DREP(i,a,b) for(register int i=(a),_end_=(b);i>=_end_;i--)
     11 #define EREP(i,a) for(register int i=start[(a)];i;i=e[i].next)
     12 inline int read()
     13 {
     14     int sum=0,p=1;char ch=getchar();
     15     while(!(('0'<=ch && ch<='9') || ch=='-'))ch=getchar();
     16     if(ch=='-')p=-1,ch=getchar();
     17     while('0'<=ch && ch<='9')sum=sum*10+ch-48,ch=getchar();
     18     return sum*p;
     19 }
     20 
     21 const int maxn=3e5+20;
     22 
     23 struct node {
     24     int cnt,val,ch[2],fa,sz;//每个节点维护两个信息,该点所代表的值和以该点为根的树的节点个数,cnt表示是这个值的数的个数
     25 };
     26 node t[maxn];
     27 int n,root=0,sz;
     28 
     29 void init()
     30 {
     31     n=read();
     32 }
     33 
     34 void push_up(int u)//维护以u点为根的树的节点个数
     35 {
     36     t[u].sz=t[t[u].ch[0]].sz+t[t[u].ch[1]].sz+t[u].cnt;
     37 }
     38 
     39 void rotate(int x)
     40 {
     41     int y=t[x].fa,z=t[y].fa,k=t[y].ch[1]==x;
     42     t[z].ch[t[z].ch[1]==y]=x;t[x].fa=z;
     43     t[y].ch[k]=t[x].ch[k^1];t[t[x].ch[k^1]].fa=y;
     44     t[x].ch[k^1]=y;t[y].fa=x;push_up(y);push_up(x);
     45 }
     46 
     47 void Splay(int x,int goal)
     48 {
     49     while(t[x].fa!=goal)
     50     {
     51         int y=t[x].fa,z=t[y].fa;
     52         if(t[y].fa!=goal)
     53         {
     54             ((t[y].ch[0]==x)^(t[z].ch[0]==y))?rotate(x):rotate(y);
     55         }
     56         rotate(x);
     57     }
     58     if(!goal)root=x;
     59 }
     60 
     61 void newt(int fa,int id,int val)
     62 {
     63     t[id]={1,val,{0,0},fa,1};
     64 }
     65 
     66 void insert(int x)
     67 {
     68     int u=root,fa=0;
     69     while(u && t[u].val!=x){fa=u;u=t[u].ch[x>t[u].val];}
     70     if(u)t[u].cnt++;
     71     else
     72     {
     73         u=++sz;
     74         if(fa)t[fa].ch[x>t[fa].val]=u;
     75         newt(fa,sz,x);
     76     }
     77     Splay(u,0);
     78 }
     79 
     80 void Find(int x)
     81 {
     82     int u=root;if(!u)return;
     83     while(t[u].ch[x>t[u].val] && x!=t[u].val)
     84     {
     85         u=t[u].ch[x>t[u].val];
     86     }
     87     Splay(u,0);
     88 }
     89 
     90 int Nxt(int x,int f)//求前驱和后继
     91 {
     92     Find(x);
     93     int u=root;
     94     if((t[u].val>x && f)|| (t[u].val<x && !f))return u;
     95     u=t[u].ch[f];
     96     while(t[u].ch[f^1])u=t[u].ch[f^1];
     97     return u;
     98 }
     99 
    100 void Del(int x)//找出前驱和后继后,把前驱变成根,后继变成根的右儿子,要删除的点就是后继的左儿子
    101 {
    102     int last=Nxt(x,0),next=Nxt(x,1);
    103     Splay(last,0);Splay(next,last);
    104     int del=t[next].ch[0];
    105     if(t[del].cnt>1)t[del].cnt--,Splay(del,0);
    106     else t[next].ch[0]=0;
    107 }
    108 
    109 int kth(int x)
    110 {
    111     int u=root;
    112     if(t[u].sz<x)return 0;
    113     while(1)
    114     {
    115         int y=t[u].ch[0];
    116         if(x>t[y].sz+t[u].cnt)
    117         {
    118             x-=t[y].sz+t[u].cnt;
    119             u=t[u].ch[1];
    120         }
    121         else if(t[y].sz>=x)
    122             u=y;
    123         else
    124             return t[u].val;
    125     }
    126 }
    127 
    128 void doing()
    129 {
    130     insert(-0x7fffffff); insert(0x7fffffff);//必须要在两边加个点,不然可能找不到前驱或后继
    131     REP(i,1,n)
    132     {
    133         int opt=read(),x=read();
    134         if(opt==1)
    135         {
    136             insert(x);
    137         }
    138         else if(opt==2)
    139         {
    140             Del(x);
    141         }
    142         else if(opt==3)
    143         {
    144             Find(x);
    145             cout<<t[t[root].ch[0]].sz<<endl;//前面加了一个点,所以计算排名要减去1
    146         }
    147         else if(opt==4)
    148         {
    149             cout<<kth(x+1)<<endl;//同理,在查找排名时要加1
    150         }
    151         else if(opt==5)
    152         {
    153             cout<<t[Nxt(x,0)].val<<endl;
    154         }else
    155         {
    156             cout<<t[Nxt(x,1)].val<<endl;
    157         }
    158     }
    159 }
    160 
    161 int main()
    162 {
    163     init();
    164     doing();
    165     return 0;
    166 }

      

  • 相关阅读:
    shaderlab
    Unity
    Lua-闭包
    Unity- 小“东西”
    3.神经网络的保存、神经网络提取的2 ways
    2.搭建pytorch神经网络的常用两种方式
    搭建pytorch神经网络的常用两种方式
    1.建立第一个神经网络-关系拟合 (回归)
    python的编码解码问题
    github的搜素小技巧
  • 原文地址:https://www.cnblogs.com/gzy-cjoier/p/7228662.html
Copyright © 2011-2022 走看看