zoukankan      html  css  js  c++  java
  • BZOJ3224 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)

    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]

    数据如下http://pan.baidu.com/s/1jHMJwO2

    正解:splay or treap or 替罪羊树

    解题报告:

      正解好多。

      感觉写的比较好的题解:(传送门)

      替罪羊树:https://zhuanlan.zhihu.com/p/21263304

      treap:http://hzwer.com/1712.html

      我也用几种算法都写了一遍。

      替罪羊树:

        感觉就是优化暴力,唯一比二叉搜索树更优秀的就是删除操作和重构操作,还是很神的。

        代码如下:(我的常数取得是0.75,事实上可以再大一点)  

      1 //It is made by jump~
      2 #include <iostream>
      3 #include <cstdlib>
      4 #include <cstring>
      5 #include <cstdio>
      6 #include <cmath>
      7 #include <algorithm>
      8 #include <ctime>
      9 #include <vector>
     10 #include <queue>
     11 #include <map>
     12 #include <set>
     13 #ifdef WIN32   
     14 #define OT "%I64d"
     15 #else
     16 #define OT "%lld"
     17 #endif
     18 using namespace std;
     19 typedef long long LL;
     20 const int MAXN = 200011;
     21 const double A = 0.75;
     22 int n,root,tot;
     23 int ret;//判断是否需要重构
     24 int son[MAXN][2],w[MAXN],del[MAXN],size[MAXN],zong[MAXN];
     25 //size记录当前未被删除的结点个数,zong记录结点个数
     26 int q[MAXN],tail,father[MAXN];
     27 
     28 inline int getint()
     29 {
     30        int w=0,q=0;
     31        char c=getchar();
     32        while((c<'0' || c>'9') && c!='-') c=getchar();
     33        if (c=='-')  q=1, c=getchar();
     34        while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
     35        return q ? -w : w;
     36 }
     37 
     38 inline bool bad(int x){
     39     return (zong[son[x][0]]>zong[x]*A) || (zong[son[x][1]]>zong[x]*A);
     40 }
     41 
     42 inline void clear(int x,int zhi){
     43     son[x][0]=son[x][1]=0;
     44     del[x]=0; size[x]=zong[x]=1;
     45     w[x]=zhi;
     46 }
     47 
     48 inline void insert(int x,int o,int f){
     49     if(!o) { clear(n,x); father[n]=f; son[f][x>=w[f]]=n; return ; }
     50     if(x>=w[o]) insert(x,son[o][1],o);
     51     else insert(x,son[o][0],o);
     52     size[o]++; zong[o]++; if(bad(o)) ret=o;
     53 }
     54 
     55 inline void update(int x){
     56     int l=son[x][0],r=son[x][1];
     57     size[x]=size[l]+size[r]+(del[x]^1);
     58     zong[x]=zong[l]+zong[r]+1;
     59 }
     60 
     61 inline void build(int l,int r,int f,int fx){
     62     if(l>r) return ;
     63     int mid=(l+r)/2;
     64     son[q[mid]][0]=son[q[mid]][1]=father[q[mid]]=del[q[mid]]=0;
     65     if(!f) root=q[mid]; else father[q[mid]]=f;
     66     son[f][fx]=q[mid]; 
     67     if(l==r) {size[q[l]]=1;zong[q[l]]=1;son[q[l]][0]=son[q[l]][1]=0;return;}//!!!   
     68     build(l,mid-1,q[mid],0); build(mid+1,r,q[mid],1);
     69     update(q[mid]);
     70 }
     71 
     72 inline void mid_dfs(int x){//中序遍历
     73     if(son[x][0]) mid_dfs(son[x][0]);
     74     if(!del[x]) q[++tail]=x;
     75     if(son[x][1]) mid_dfs(son[x][1]);
     76 }
     77 
     78 inline void rebuild(int x){//替罪羊树的重构
     79     tail=0; mid_dfs(x);
     80     build(1,tail,father[x],(son[father[x]][1]==x));
     81 }
     82 
     83 inline int rank(int x){//求x的排名
     84     int t=root; int now=1;
     85     while(t) {
     86     if(x<=w[t]) t=son[t][0];
     87     else {
     88         now+=(size[son[t][0]]+(del[t]^1));
     89         t=son[t][1];
     90     }
     91     }
     92     return now;
     93 }
     94 
     95 inline int kth(int x){//查找排名为x的数
     96     int t=root;
     97     while(t) {
     98     if(x==size[son[t][0]]+1 && !del[t]) return w[t];
     99     if(size[son[t][0]]>=x) t=son[t][0];
    100     else { x-=size[son[t][0]]+(del[t]^1); t=son[t][1]; }
    101     }
    102 }
    103 
    104 inline void out(int x,int o){//删除排名为x的一个点,删除的点打上标记即可
    105     size[o]--;
    106     int p=size[son[o][0]]+(del[o]^1);
    107     if(p==x && !del[o]) {  del[o]=1; return ; }
    108     if(x<=p) out(x,son[o][0]);
    109     else out(x-p,son[o][1]);
    110 }
    111 
    112 inline void work(){
    113     int T=getint(); int ljh,x;
    114     while(T--) {
    115     ljh=getint(); x=getint();
    116     if(ljh==1) { 
    117         n++; tot++;
    118         if(tot==1) { root=1; clear(1,x); }
    119         else { ret=0; insert(x,root,0); if(ret) rebuild(ret); }  
    120     }
    121     else if(ljh==2) { tot--; out(rank(x+1)-1,root); if(size[root]<zong[root]*A) rebuild(root);  }//已经删除的结点个数超过设定限制
    122     else if(ljh==3) printf("%d
    ",rank(x));
    123     else if(ljh==4) printf("%d
    ",kth(x));
    124     else if(ljh==5) printf("%d
    ",kth(rank(x)-1));
    125     else printf("%d
    ",kth(rank(x+1)));
    126     }
    127 }
    128 
    129 int main()
    130 {
    131   work();
    132   return 0;
    133 }
  • 相关阅读:
    spring对事务的配置
    Mysq中的流程控制语句的用法
    mysql存储过程和常用流程控制
    ztree更换节点图标
    eclipse调试(debug)的时候,出现Source not found,Edit Source Lookup Path,一闪而过
    myeclipse如何设置或关闭断点调试自动跳入debug模式
    Druid数据源对数据库访问密码加密好麻烦
    js中if()条件中变量为false的情况
    TFS2008 安装图解(详细版本)(转载)
    数字格式化
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/5692136.html
Copyright © 2011-2022 走看看