• 算法复习——splay(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模板题···表示两周没碰键盘手都生了····

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<ctime>
    #include<cctype>
    #include<cstring>
    #include<string>
    #include<algorithm>
    using namespace std;
    const int N=100005;
    int root,size[N],son[N][2],key[N],cnt[N],tot,father[N];
    int a,b,n;
    inline void clear(int now)
    {
      size[now]=son[now][0]=son[now][1]=key[now]=cnt[now]=father[now]=0;
    }
    inline void update(int now)
    {
      if(now)
      {
        size[now]=cnt[now];
        if(son[now][0])  size[now]+=size[son[now][0]];
        if(son[now][1])  size[now]+=size[son[now][1]];
      }
    }
    inline int get(int a)
    {
      return son[father[a]][1]==a;
    }
    inline void rotate(int now)
    {
      int fa=father[now],ofa=father[fa],which=get(now);
      son[fa][which]=son[now][which^1],father[son[fa][which]]=fa;
      son[now][which^1]=fa,father[fa]=now,father[now]=ofa;
      if(ofa)  son[ofa][son[ofa][1]==fa]=now;
      update(fa),update(now);
    }
    inline void splay(int now)
    {
      while(father[now])
      {
        if(father[father[now]])  rotate(get(now)==get(father[now])?father[now]:now);
        rotate(now);
      }
      root=now;
    }
    inline void insert(int x)
    { 
      int now=root,last=0;
      while(true)
      {
        if(!now)
        {
          now=++tot;size[now]=cnt[now]=1;father[now]=last;key[now]=x;
          son[last][key[now]>key[last]]=now;update(last);splay(now);
          break;
        }
        if(key[now]==x)
        {
          cnt[now]++;update(now);update(last);splay(now);
          break;
        }
        last=now;now=son[now][x>key[now]];
      }
    }
    inline int find(int x)
    {
      int now=root,ans=0;
      while(true)
      {
        if(x<key[now])  now=son[now][0];
        else
        {
          ans+=size[son[now][0]];
          if(x==key[now])  {splay(now);return ans+1;}
          ans+=cnt[now];now=son[now][1];
        }
      }
    }
    inline int findx(int x)
    {
      int now=root;
      while(true)
      {
        if(x<=size[son[now][0]])  now=son[now][0];
        else
        {
          int temp=size[son[now][0]]+cnt[now];
          if(x<=temp)  return key[now];
          x-=temp;now=son[now][1];
        }  
      }
    }
    inline int pre()
    {
      int now=son[root][0];
      while(son[now][1])  now=son[now][1];
      return now;
    }
    inline int next()
    {
      int now=son[root][1];
      while(son[now][0])  now=son[now][0];
      return now;
    }
    inline void Delete(int x)
    {
      int nothing=find(x);
      if(cnt[root]>1) {cnt[root]--;return;}
      else if(!son[root][0]&&!son[root][1])  
      {clear(root);root=0;return;}
      else if(!son[root][0])
      {int oldroot=root;root=son[root][1];father[root]=0;clear(oldroot);return;}
      else if(!son[root][1])
      {int oldroot=root;root=son[root][0];father[root]=0;clear(oldroot);return;}
      else 
      {
        int leftbig=pre(),oldroot=root;
        splay(leftbig);son[root][1]=son[oldroot][1];
        father[son[root][1]]=root;clear(oldroot);
        update(root);
        return;
      }
    }
    inline int findpre(int x)
    {
      insert(x);int temp=pre();
      Delete(x);return key[temp];
    }
    inline int findnext(int x)
    {
      insert(x);int temp=next();
      Delete(x);return key[temp];
    }
    int main()
    {
      //freopen("a.in","r",stdin);
      scanf("%d",&n);
      for(int i=1;i<=n;i++)
      {
        scanf("%d%d",&a,&b);
        if(a==1)
          insert(b);
        if(a==2)
          Delete(b);
        if(a==3)
        {
          int temp=find(b);
          printf("%d
    ",temp);
        }
        if(a==4)
        {
          int temp=findx(b);
          printf("%d
    ",temp);
        }
        if(a==5)
        {
          int temp=findpre(b);
          printf("%d
    ",temp);
        }
        if(a==6)
        {
          int temp=findnext(b);
          printf("%d
    ",temp);
        }
       }
      return 0;
    }
  • 相关阅读:
    剑指Offer——数组中重复的数字
    基于Google Protobuff和Mina的RPC
    Google Protocol Buffers 编码(Encoding)
    Protocol Buffers 语法指南
    Google Protocol Buffers 入门
    Google Protocol Buffers 概述 转
    Protobuf语言指南
    基于Protobuf的通讯库--Poppy简介
    log4cxx第三篇----使用多个logger
    log4CXX第二篇---配置文件(properties文件)详解
  • 原文地址:https://www.cnblogs.com/AseanA/p/6783198.html
Copyright © 2020-2023  润新知