zoukankan      html  css  js  c++  java
  • 洛谷 P3391【模板】文艺平衡树(Splay)

    题目背景

    这是一道经典的Splay模板题——文艺平衡树。

    题目描述

    您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1

    输入输出格式

    输入格式:

    第一行为n,m n表示初始序列有n个数,这个序列依次是 (1,2, cdots n-1,n)(1,2,⋯n−1,n) m表示翻转操作次数

    接下来m行每行两个数 [l,r][l,r] 数据保证 1 leq l leq r leq n 1≤l≤r≤n

    输出格式:

    输出一行n个数字,表示原始序列经过m次变换后的结果

    输入输出样例

    输入样例#1:

    5 3
    1 3
    1 3
    1 4
    

    输出样例#1:

    4 3 2 1 5
    

    说明

    (n, m leq 100000)

    思路见注释。

    代码:

    #include<iostream>
    #include<cstdio>
    #define maxn 200001
    using namespace std;
    inline int qread() {
      char c=getchar();int num=0,f=1;
      for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
      for(;isdigit(c);c=getchar()) num=num*10+c-'0';
      return num*f;
    }
    struct tree {
      int ch[2];
      int ff,v,size,lazy;
      void init(int x,int fa) {
        ff=ch[0]=ch[1]=0;
        size=1;
        v=x;
        ff=fa;
      }
    } t[maxn];
    int n,root,m,tot;
    inline void pushup(int x) {
      t[x].size=t[t[x].ch[0]].size+t[t[x].ch[1]].size+1;
    }
    inline void pushdown(int x) {
      if(t[x].lazy) {
        t[t[x].ch[0]].lazy^=1;
        t[t[x].ch[1]].lazy^=1;
        t[x].lazy=0;
        swap(t[x].ch[0],t[x].ch[1]);
      }
    }
    void rotate(int x) {
      int y=t[x].ff;        //x的父亲 。
      int z=t[y].ff;         //x的爷爷。
      int k=t[y].ch[1]==x;         //x是y的哪一个儿子。
      t[z].ch[t[z].ch[1]==y]=x;  //z的原来的y的位置变为x。
      t[x].ff=z;                    //x的父亲变为z。
      t[y].ch[k]=t[x].ch[k^1];      //x的与x原来在y的相对的那个儿子变成y的儿子。
      t[t[x].ch[k^1]].ff=y;     //更新父节点。
      t[x].ch[k^1]=y;        //x的与x原来相对位置的儿子变成y。
      t[y].ff=x;       //更新父节点。
      pushup(y);
      pushup(x);
    }
    inline void splay(int x,int goal) { //将x转为goal的儿子,若x为0,则旋转为根。
      while(t[x].ff!=goal) {    //一直转到x成为goal的儿子。
        int y=t[x].ff,z=t[y].ff;     //父节点祖父节点。
        if(z!=goal)
          (t[z].ch[0]==y)^(t[y].ch[0]==x)?rotate(x):rotate(y);  //分情况。
        rotate(x);          //无论什么情况都要最后旋转x。
      }
      if(!goal)             //若goal为0,则更新x为根节点。
        root=x;
    }
    inline void insert(int x) {
      int u=root,ff=0;
      while(u) ff=u,u=t[u].ch[x>t[u].v];
      u=++tot;
      if(ff) t[ff].ch[x>t[ff].v]=u;
      t[u].init(x,ff);
      splay(u,0);
    }
    inline int kth(int k) {
      int u=root;
      while(1) {
        pushdown(u);
        if(t[t[u].ch[0]].size>=k) u=t[u].ch[0];
        else if(t[t[u].ch[0]].size+1==k) return u;
        else k-=t[t[u].ch[0]].size+1,u=t[u].ch[1];
      }
    }
    void write(int u) {
      pushdown(u);
      if(t[u].ch[0]) write(t[u].ch[0]);
      if(t[u].v>1&&t[u].v<n+2) printf("%d ",t[u].v-1);
      if(t[u].ch[1]) write(t[u].ch[1]);
    }
    inline void work(int l,int r) {
      l=kth(l);
      r=kth(r+2);
      splay(l,0);
      splay(r,l);
      t[t[t[root].ch[1]].ch[0]].lazy^=1;
    }
    int main() {
      n=qread(),m=qread();
      for(int i=1; i<=n+2; ++i) insert(i);
      while(m--) {
        int l=qread(),r=qread();
        work(l,r);
      }
      write(root);
      printf("
    ");
      return 0;
    }
    
  • 相关阅读:
    HDU 5360 Hiking(优先队列)2015 Multi-University Training Contest 6
    多区域显示(6)-版面布局
    静态变量和成员变量的区别 && 成员变量和局部变量的区别
    java基础学习_面向对象(上)02_day07总结
    java基础学习_面向对象(上)01_day07总结
    面向对象的概述
    面向对象思想的引入
    Failed to create the Java Virtual Machine(zt)
    eclipse web开发Server配置
    javamail接收邮件(zt)
  • 原文地址:https://www.cnblogs.com/grcyh/p/10569516.html
Copyright © 2011-2022 走看看