zoukankan      html  css  js  c++  java
  • [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.每个数的数据范围:[-2e9,2e9]

    题解:

    splay

    操作前要设一个上界-inf,防止访问上界时把空结点转到根......

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    #define RG register
    using namespace std;
    
    const int maxn = 100010;
    
    int n,id,root,inf=1<<30;
    int ch[maxn][2],key[maxn],pre[maxn],siz[maxn];
    
    void newnode(int &x, int fa, int val) {
      x=++id,key[x]=val,pre[x]=fa;
      ch[x][1]=ch[x][0]=0;
    }
    
    void rotate(int x, int kd) {
      int y=pre[x];
      ch[y][!kd]=ch[x][kd];
      pre[ch[x][kd]]=y;
      if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x;
      pre[x]=pre[y],ch[x][kd]=y,pre[y]=x;
      siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
      siz[y]=siz[ch[y][0]]+siz[ch[y][1]]+1;
    }
    
    void splay(int x, int goal) {
      while(pre[x]!=goal) {
        if(pre[pre[x]]==goal) rotate(x,ch[pre[x]][0]==x); 
        else {
          int y=pre[x],kd=ch[pre[y]][0]==y;
          if(ch[y][!kd]==x) rotate(y,kd),rotate(x,kd);
          else rotate(x,!kd),rotate(x,kd);
        }
      }
      if(goal==0) root=x;
    }
    
    void insert(int k) {
      while(ch[root][k>key[root]]) {
        siz[root]++;
        root=ch[root][k>key[root]];
      }
      siz[root]++;
      newnode(ch[root][k>key[root]],root,k);
      siz[ch[root][k>key[root]]]++;
      splay(ch[root][k>key[root]],0);
    }
    
    void find_pre(int x, int k, int &ans) {
      if(!x) return;
      if(k>key[x]) {ans=x,find_pre(ch[x][1],k,ans);return;}
      else {find_pre(ch[x][0],k,ans);return;}
    }
    
    void find_nxt(int x, int k, int &ans) {
      if(!x) return;
      if(k<key[x]) {ans=x,find_nxt(ch[x][0],k,ans);return;}
      else {find_nxt(ch[x][1],k,ans);return;}
    }
    
    void erase(int k) {
      int prek=root; find_pre(root,k,prek);
      int nxtk=root; find_nxt(root,k,nxtk);
      splay(prek,0),splay(nxtk,prek);
      int tmp=ch[nxtk][0];
      while(ch[tmp][0] || ch[tmp][1]) {
        siz[tmp]--;
        if(ch[tmp][0]) tmp=ch[tmp][0];
        else tmp=ch[tmp][1];
      }
      if(ch[pre[tmp]][0]==tmp) ch[pre[tmp]][0]=0;
      else ch[pre[tmp]][1]=0;
    }
    
    void query_rank(int k) {
      int prek=root; find_pre(root,k,prek);
      splay(prek,0);
      printf("%d
    ", siz[ch[root][0]]+1);
    }
    
    void query_num(int k) {//k是排名
      int rt=root;
      while(rt) {
        if(siz[ch[rt][0]]+1==k) {printf("%d
    ", key[rt]);return;}
        if(siz[ch[rt][0]]<k) k-=siz[ch[rt][0]]+1,rt=ch[rt][1];
        else rt=ch[rt][0];
      }
    }
    
    void query_pre(int x, int k, int &ans) {
      if(!x) return;
      if(k>key[x]) {ans=key[x],query_pre(ch[x][1],k,ans);return;}
      else {query_pre(ch[x][0],k,ans);return;}
    }
    
    void query_nxt(int x, int k, int &ans) {
      if(!x) return;
      if(k<key[x]) {ans=key[x],query_nxt(ch[x][0],k,ans);return;}
      else {query_nxt(ch[x][1],k,ans);return;}
    }
    
    int main() {
      scanf("%d", &n);
      newnode(root,0,-inf),insert(inf);
      for(int i=1; i<=n; i++) {
        int kd,x;
        scanf("%d%d", &kd, &x);
        if(kd==1) insert(x);
        if(kd==2) erase(x);
        if(kd==3) query_rank(x);
        if(kd==4) query_num(x+1);
        if(kd==5) {
          int ans=-1;
          query_pre(root,x,ans);
          printf("%d
    ", ans);
        }
        if(kd==6) {
          int ans=-1;
          query_nxt(root,x,ans);
          printf("%d
    ", ans);
        }
      }
      return 0;
    }
  • 相关阅读:
    0514JS基础:操作document对象、事件、this
    Java 多态
    Java 抽象类和接口
    Vue中v-for属性
    Vue基础语法
    Vue 自定义按键修饰符,自定义指令,自定义过滤器
    ES6 剩余参数
    ES6 箭头函数
    ES6 解构赋值
    ES6 变量声明 var let const的区别
  • 原文地址:https://www.cnblogs.com/HLXZZ/p/7262729.html
Copyright © 2011-2022 走看看