zoukankan      html  css  js  c++  java
  • 伸展树模版题 hdu

    #include <map>
    #include <set>
    #include <list>
    #include <queue>
    #include <deque>
    #include <stack>
    #include <string>
    #include <cstdio>
    #include <math.h>
    #include <iomanip>
    #include <cstdlib>
    #include <limits.h>
    #include <string.h>
    #include <iostream>
    #include <fstream>
    #include <algorithm>
    using namespace std;
    
    #define LL long long
    #define pii pair<int ,int>
    #define bug cout<<"here!!"<<endl
    #define PI acos(-1.0)
    #define FRE freopen("input.txt","r",stdin)
    #define FF  freopen("output.txt","w",stdout)
    #define eps 1e-8
    #define MIN INT_MIN
    #define inf 1<<30
    #define N 3*100100
    //#define DEBUG_ENABLE 1
    struct SplayTree{
           int sz[N];             //sz[x]-以x为根结点子树的结点数量
           int ch[N][2];          //ch[x][0]-x的左子节点;ch[x][1]-x的右子节点
           int pre[N];            //pre[x]-x的父结点
           int root,top1,top2;       //root-根结点;top1-未用结点队列头指针;top2-结点回收栈的栈顶指针
           int ss[N],que[N];
    
    /***********************************以下代码基本不变*********************************************/
           /* Rotate(x,f):f=0-将x点左旋;f=1-将x点右旋 */
           inline void rotate(int x,int f){
              int y=pre[x];
              push_down(y);
              push_down(x);
              ch[y][!f]=ch[x][f];
              pre[ch[x][f]]=y;
              pre[x]=pre[y];
              if(pre[y])
                 if(ch[pre[y]][0]==y) ch[pre[y]][0]=x;
                 else ch[pre[y]][1]=x;
              ch[x][f]=y;
              pre[y]=x;
              push_up(y);
           }
    
           /* splay(x,goal):将x结点伸展为goal结点的子节点 */
           inline void splay(int x,int goal){
               for(push_down(x);pre[x]!=goal;){
                   if(pre[pre[x]]==goal){   /* x节点的父结点的父结点为goal,进行单旋转 */
                       if(ch[pre[x]][0]==x) rotate(x,1);
                       else rotate(x,0);
                   }
                   else{
                        int y=pre[x];
                        int z=pre[y];
                        if(ch[z][0]==y)
                          if(ch[y][0]==x){    /* 一字形旋转 */
                             rotate(y,1);
                             rotate(x,1);
                          }
                          else{               /* 之字形旋转 */
                             rotate(x,0);
                             rotate(x,1);
                          }
                        else
                          if(ch[y][1]==x){    /* 一字形旋转 */
                             rotate(y,0);
                             rotate(x,0);
                          }
                          else{               /* 之字形旋转 */
                             rotate(x,1);
                             rotate(x,0);
                          }
                   }
                   push_up(x);
                   if(goal==0) root=x;
               }
           }
    
           /* rotateTo(k,goal):将序列中第k个数转到goal的子节点 */
           inline void rotateTo(int k,int goal){
                /* 第k位要利用中序遍历来查找 */
                int tmp,t;
                for(t=root;;){
                    push_down(t);        /* 标记下延 */
                    tmp=sz[ch[t][0]];
                    if(k==tmp+1) break;
                    if(k<=tmp)           /* 第k个节点在t的左子树,向左遍历 */
                        t=ch[t][0];
                    else{
                        k-=tmp+1;
                        t=ch[t][1];
                    }
                }
                splay(t,goal);
           }
    
           /* join(s1,s2):将s1和s2两个Splay Tree合并为一个Splay Tree,s1的所有结点都小于s2的所有结点;返回合并后的根节点 */
           inline int join(int s1,int s2){
                if(s1&&s2){
                    int right_end=getEnd(s1,1);
                    splay(right_end,pre[s1]);
                    ch[right_end][1]=s2;
                    pre[s2]=right_end;
                    push_up(right_end);
                    return right_end;
                }
                if(s1) return s1;
                if(s2) return s2;
                return 0;
           }
    
           /* erase(x):把x为节点的子树删除,放到内存池 */
           inline void erase(int x){
                int head,tail;
                for(que[tail++]=x;head<tail;head++){
                    ss[top2++]=que[head];
                    if(ch[que[head]][0]) que[tail++]=ch[que[head]][0];
                    if(ch[que[head]][1]) que[tail++]=ch[que[head]][1];
                }
           }
    
           /* eraseNode(x): 将x结点删除,其子树进行和并 */
           inline void eraseNode(int x){
                int ret = join(ch[x][0],ch[x][1]);
                if(pre[x]){
                   if(ch[pre[x]][0]==x)
                     ch[pre[x]][0]=ret;
                   else
                     ch[pre[x]][1]=ret;
                }
                else{
                   root=ret;
                }
                if(ret)
                  pre[ret]=pre[x];
                if(pre[x])
                  splay(pre[x],0);
           }
    
           /* getEnd(x,c): 得到x节点最边缘的节点 c=0 最左边的, c=1 最右边的 */
           inline int getEnd(int x,int c){
                 push_down(x);
                 while(ch[x][c]){
                     x=ch[x][c];
                     push_down(x);
                 }
                 return x;
           }
    
           /* getNear(x,c): 得到x节点最近的节点 c=0 前驱节点, c=1 后继节点 */
           inline int getNear(int x,int c){
                  if(ch[x][c]){
                      return getEnd(ch[x][c],1-c);
                  }
                  while(pre[x]&&ch[pre[x]][c]==x)
                     x=pre[x];
                  return pre[x];
           }
    
           /* getSucc(x): 得到x节点的后继节点 */
           inline int getSucc(int x) { return getNear(x,1); }
    
           /* getPrev(x): 得到x节点的前驱节点 */
           inline int getPrev(int x) { return getNear(x,0); }
    
    /*****************************************END*********************************************/
    /**********************************以下代码会随着题目的不同改变****************************/
    
            /* 标记结点 */
            inline void markNode(int x){
                   if(x){
                      _rev[x]=!_rev[x];
                      /*swap(ch[x][0],ch[x][1])交换左右结点*/
                      int tmp;
                      tmp=ch[x][0];
                      ch[x][0]=ch[x][1];
                      ch[x][1]=tmp;
                   }
            }
    
           /* push_down 把延迟标记推到孩子 */
           inline void push_down(int x){
                  if(_rev[x]){
                       markNode(ch[x][0]);
                       markNode(ch[x][1]);
                       _rev[x]=false;
                  }
           }
    
           /* push_up 把孩子的状态更新上来 */
           inline void push_up(int x){
               sz[x]=1+sz[ch[x][0]]+sz[ch[x][1]];
           }
    
           /* findKthNode(int k): 在Splay Tree中找到第k个节点 */
           inline int findKthNode(int k){
                /* 第k位要利用中序遍历来查找 */
                int tmp,t;
                for(t=root;;){
                    push_down(t);        /* 标记下延 */
                    tmp=sz[ch[t][0]];
                    if(k==tmp+1) break;
                    if(k<=tmp)           /* 第k个节点在t的左子树,向左遍历 */
                        t=ch[t][0];
                    else{
                        k-=tmp+1;
                        t=ch[t][1];
                    }
                }
                return t;
           }
    
           /* To create a new node 题目不同,函数内容不同 */
           inline void newNode(int &x,int m){
               if(top2) x=ss[--top2];
               else x=++top1;
    
               ch[x][0]=ch[x][1]=pre[x]=0;
               sz[x]=1;
    
               val[x]=m;
               _rev[x]=false;
           }
    
           /* To build a splay tree 题目不同,函数内容不同 */
           inline void makeTree(int &x,int l,int r,int f){//x-son,f-father
               if(l>r) return ;
               int m=(r+l)>>1;
               newNode(x,m);
               makeTree(ch[x][0],l,m-1,x);
               makeTree(ch[x][1],m+1,r,x);
               pre[x]=f;
               push_up(x);
           }
    
           /* 初始化函数(调用建树函数),题目不同,函数内容不同 */
           inline void init(int n){
               ch[0][0]=ch[0][1]=pre[0]=sz[0]=0;
    
               root=top1=top2=0;
    
               /* 增加第一个边界结点 */
    
               /* Read into the Datas */
    
               /* 增加第二个边界节点 */
    
               makeTree(root,0,n,0);
               push_up(root);
           }
    
           /* update 更新函数 题目不同内容不同 */
           inline void update(){
           }
           /* query 查询函数 题目不同内容不同 */
           inline void query(){
           }
           /* run() */
           inline void run(int n,int m){
               int i;
               for(i=0;i<m;i++){
                   char in[5];
                   scanf("%s",in);
                   int a,b,c;
                   if(in[0]=='C'){//先切再插入一段
                      scanf("%d%d%d",&a,&b,&c);
                      a=findKthNode(a);
                      splay(a,0);
    
                      b=findKthNode(b+2);
                      splay(b,root);
    
                      int cut=ch[b][0];//cut是要操作的区间子树的根
                      //push_down(b);  //
                      ch[b][0]=0;
                      //splay(b,0);
    
                      a=findKthNode(c+1);
                      splay(a,0);//将a转到根
    
                      b=getSucc(a);//后继
                      splay(b,root);//后继转到根的右子结点
    
                      ch[b][0]=cut;//把切出来的子树挂到根右子结点的左子结点上
                      pre[cut]=b;
                      splay(b,0);
                      //debug();
                   }
                   else{//翻转
                      scanf("%d%d",&a,&b);
                      a=findKthNode(a);
                      splay(a,0);
    
                      b=findKthNode(b+2);
                      splay(b,root);
    
                      markNode(ch[b][0]);//交换左右结点
                   }
    
               }
               num = -1;
               outputNode(root,n);
               printf("\n");
           }
    
           /* binarySearch(k): 查找第k号人 */
           inline int binarySearch(int k,int n){
                  return 0;
           }
    
           /* isSmaller(a,b): val[a]<val[b] retrun 1*/
           inline int isSmaller(int a,int b){
                  return 0;
           }
    
           /*output(x,n): 中序遍历输出节点值,最左和最右的值不输出 */
           inline void outputNode(int x,int n){
                  if(x){
                      push_down(x);
                      outputNode(ch[x][0],n);//先遍历左
                      num++;
                      if(num!=0&&num!=n+1){
                         if(num==n) printf("%d",val[x]);
                         else printf("%d ",val[x]);
                      }
                      outputNode(ch[x][1],n);//再遍历右
                  }
           }
    
           /* Optional Variables 题目不同,变量不同 */
           int val[N];
           bool _rev[N];
           int num;
    /*****************************************END**********************************************/
    
    /****************************************Debug*********************************************/
    #if (DEBUG_ENABLE == 1)
           void debug() {printf("%d\n",root);Treaval(root);}
           void Treaval(int x) {
                if(x) {
                    printf("结点 %2d: 左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d val = %2d rev = %2d\n",x,ch[x][0],ch[x][1],pre[x],sz[x],val[x],_rev[x]);
                    Treaval(ch[x][0]);
                    Treaval(ch[x][1]);
                }
           }
    #endif
    /*****************************************END**********************************************/
    }spt;
    int main(){
        int n,m;
        while(scanf("%d%d",&n,&m) && n != -1 && m != -1){
            spt.init(n+1);
            //spt.debug();
            spt.run(n,m);
        }
        return 0;
    }
  • 相关阅读:
    kali网卡配置文件
    haproxy配置文件详解和ACL功能
    Linux查询端口是否被占用的四种方法
    为Linux配置常用源:epel和IUS
    高可用之KeepAlived(2):keepalived+lvs
    高可用之KeepAlived(一):基本概念和配置文件分析
    应用负载均衡之LVS(四):详细剖析VS/NAT和VS/DR模式
    应用负载均衡之LVS(二):VS_TUN和VS_DR的arp问题
    wget命令的几个常用选项和示例
    应用负载均衡之LVS(一):基本概念和三种模式
  • 原文地址:https://www.cnblogs.com/LUO257316/p/3220825.html
Copyright © 2011-2022 走看看