zoukankan      html  css  js  c++  java
  • 【题解】 [ZJOI2006]书架 (Splay)

    懒得复制,戳我戳我

    Solution:

    • 还是一个(Splay),我们只用多存一个值(rad)来维护二叉树,然后用数组存下每个书对应的值是多少
    • (Top)操作,我是把(s)旋转到根节点,然后删除,将(s)对应的(rad)值调至最小,然后插入就可以
    • (Bottom)操作,就是和(Top)相反,删除后把(rad)调整至最大,然后插入
    • (Insert)操作,(s==0)不用操作,(-1)时,就只用把(s)旋转到根节点,把左子树最大值旋转至左子树根节点,然后交换两个节点信息,并且交换数组储存的每个书对应的(rad)(1)就是相反的旋转右子树最小值就可以
    • (Ask)操作,就只用把(s)旋转到根节点,输出左子树大小
    • (Query)操作,就是找第(s)大的(rad)值对应的书籍编号就可以了
    • 一开始想怎么找编号好久,发现编号是(1-n)就好操作了

    Code:

    //It is coded by Ning_Mew on 4.12
    #include<bits/stdc++.h>
    #define ls(x) node[x].ch[0]
    #define rs(x) node[x].ch[1]
    #define fa(x) node[x].fa
    #define root node[0].ch[1]
    using namespace std;
    
    const int maxn=8e4+10,INF=1e9+7;
    
    int n,m,tot,vall[maxn],low=0,up=0;
    struct Node{
      int fa,ch[2],val,num,size;//num-> bian hao   val->rand()
    }node[maxn];
    
    void update(int x){node[x].size=node[ls(x)].size+node[rs(x)].size+1;}
    void connect(int x,int fa,int how){node[x].fa=fa;node[fa].ch[how]=x;}
    int ident(int x){return x==node[fa(x)].ch[0]?0:1;}
    void rorate(int x){
      int Y=fa(x),R=fa(Y);int Yson=ident(x),Rson=ident(Y);
      connect(node[x].ch[Yson^1],Y,Yson);
      connect(Y,x,Yson^1);
      connect(x,R,Rson);
      update(Y);update(x);
    }
    void Splay(int x,int goal){
      int to=fa(goal);
      while(fa(x)!=to){
        if(fa(fa(x))==to)rorate(x);
        else if(ident(x)==ident(fa(x)))rorate(fa(x)),rorate(x);
        else rorate(x),rorate(x);
      }
    }
    int newnode(int x,int rad,int fa){node[++tot].val=rad;node[tot].num=x;node[tot].size=1;node[tot].fa=fa;return tot;}
    void ins(int x,int rad){
      //cout<<x<<' '<<rad<<endl;
      int now=root;
      if(!root){newnode(x,rad,0);root=tot;return;}
      else{
        while(1){
          node[now].size++;
          int nxt=rad<node[now].val?0:1;
          if(!node[now].ch[nxt]){
    	int p=newnode(x,rad,now);
    	node[now].ch[nxt]=p;Splay(p,root);return;
          }
          now=node[now].ch[nxt];
        }
      }return;
    }
    int find(int x,int rad){
      int now=root;
      while(1){
        if(!now)return 0;
        if(node[now].val==rad){Splay(now,root);return now;}
        int nxt=rad<node[now].val?0:1;
        now=node[now].ch[nxt];
      }
    }
    void del(int x,int rad,int opt,int sum){//1->del 2->swap
      int pos=find(x,rad);
      if(!pos)return;
      if(opt==1){
        if(!ls(pos)&&!rs(pos)){root=0;return;}
        if(!ls(pos)){root=rs(pos);fa(root)=0;return;}
        else{
          int left=ls(pos);
          while(rs(left))left=rs(left);
          Splay(left,ls(pos));
          connect(rs(pos),left,1);
          connect(left,0,1);update(left);
        }
      }else{
        if(sum==0)return;
        if(sum==-1&&!ls(pos))return;
        if(sum==1&&!rs(pos))return;
        if(sum==-1){
          int left=ls(pos);
          while(rs(left))left=rs(left);
          Splay(left,ls(pos));
          swap(vall[ node[pos].num ],vall[ node[left].num ]);
          swap(node[pos].num,node[left].num);
        }else{
          int right=rs(pos);
          while(ls(right))right=ls(right);
          Splay(right,rs(pos));
          swap(vall[ node[pos].num ],vall[ node[right].num ]);
          swap(node[pos].num,node[right].num);
        }
      }
    }
    int rak(int x,int rad){int pos=find(x,rad);return node[ls(pos)].size;}
    int kth(int x,int rad){
      int now=root;
      while(1){
        if(x-node[ls(now)].size==1){
          Splay(now,root);return node[now].num;}
        int nxt=x<=node[ls(now)].size?0:1;
        if(nxt){x=x-(node[ls(now)].size+1);}
        now=node[now].ch[nxt];
      }
    }
    string s;
    int main(){
      scanf("%d%d",&n,&m);
      int x,t;
      for(int i=1;i<=n;i++){
        scanf("%d",&x);
        ins(x,++up);vall[x]=up;
      }
      //cout<<"ins finished"<<endl;
      for(int i=1;i<=m;i++){
        cin>>s;scanf("%d",&x);
        if(s=="Top"){
          del(x,vall[x],1,0);vall[x]=--low;
          ins(x,vall[x]);
        }
        if(s=="Bottom"){
          del(x,vall[x],1,0);vall[x]=++up;
          ins(x,vall[x]);
        }
        if(s=="Insert"){
          scanf("%d",&t); del(x,vall[x],2,t);
        }
        if(s=="Ask"){printf("%d
    ",rak(x,vall[x]));}
        if(s=="Query"){printf("%d
    ",kth(x,vall[x]));}
      }
      return 0;
    }
    
    
  • 相关阅读:
    阿里云遇到的坑:CentOS7防火墙(Firewalld),你关了吗?
    阿里云学生机——Mysql配置---教小白入门篇
    关于Javac编译器的那点事(一)
    B树,B+树,B*树简介
    ArrayList动态扩容机制
    满二叉树和完全二叉树
    nginx实践(二)之静态资源web服务(浏览器缓存场景)
    http之cdn介绍
    http之理解304
    nginx实践(一)之静态资源web服务
  • 原文地址:https://www.cnblogs.com/Ning-Mew/p/8811015.html
Copyright © 2011-2022 走看看