zoukankan      html  css  js  c++  java
  • Tyvj 1729 文艺平衡树(Splay)

    题目

    Description

    您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:

    翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1

    Input

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

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

    Output

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

    Sample Input

    5 3
    1 3
    1 3
    1 4
    

    Sample Output

    4 3 2 1 5
    

    HINT

    N,M<=100000

    题解

    这题我目前知道两种做法:

    1. Splay
    2. FHQ Treap

    由于暂时没写出FHQ Treap的代码(也不太实用), 以后再补

    伸展树 Splay

    初始化 init

    首先按原序列构建树,此外向树中插入0n+1,并将其size定为0,方便后面操作

    反转区间 reverse
    1. 从根结点开始,向下找到对应下标为l-1r+1的结点,每访问一个结点下传旋转标记
    2. l-1对应的结点splay到根,此时保证r+1在其右子树
    3. r+1对应的结点splay到根的右儿子处,此时保证需要操作的区间为r+1对应结点的左子树
    4. r+1对应结点的左子树进行标记,若已标记则消除标记
    得到操作后序列 c_list

    将树中序遍历(忽略0n+1)的结果保存在一个vector中返回

    详情见代码

    代码 code
    #include<cstdio>
    #include<vector>
    using namespace std;
    int f(-1);
    inline char GetCharacter() {
    	static char buf[2000000], *p1 = buf, *p2 = buf;
    	return (p1 == p2) &&
    	       (p2 = (p1 = buf) + fread(buf, 1, 2000000, stdin), p1 == p2) ? 
    	       EOF : *p1++;
    }
    #define IS_DIGIT(c) (c >= '0' && c <= '9')
    inline void Read(int &x) {
    	f = 1, x = 0;
    	static char c = GetCharacter();
    	while (!IS_DIGIT(c)) {
    		if (c == '-') f = -1;
    		c = GetCharacter();
    	}
    	while (IS_DIGIT(c)) x = x * 10 + c - '0', c = GetCharacter();
    	x *= f;
    }
    #undef IS_DIGIT
    class splay_tree {
      private:
        struct node {
          int value,delta,size;
          node *left, *right, *father;
          node(const int v = 0) {
            value = v, delta = 0, size = 1;
            left = right = father = NULL;
          }
        };
        node *root;
        int Left, Right;
        node *left_node, *right_node;
        vector<int> List;
        inline void update(register node *x) {
          if (x) x->size = (x->value < Left || x->value > Right ? 0 : 1) + 
                 (x->left ? x->left->size : 0) + 
                 (x->right ? x->right->size : 0);
        }
    #define SIZE(x) (x ? x->size : 0)
        inline void push_down(register node *x) {
          if (x) {
            if (x->delta) {
              swap(x->left, x->right);
              if (x->left) x->left->delta ^= 1;
              if (x->right) x->right->delta ^= 1;
              x->delta = 0;
            }
          }
        }
        inline void left_rotate(register node *x) {
          register node *y = x->father;
          y->right = x->left;
          if (x->left) x->left->father = y;
          x->father = y->father;
          if (y->father) {
            if (y == y->father->left) y->father->left = x;
            else y->father->right = x;
          }
          x->left = y;
          y->father = x;
          update(y);
          update(x);
        }
        inline void right_rotate(register node *x) {
          register node *y = x->father;
          y->left = x->right;
          if (x->right) x->right->father = y;
          x->father = y->father;
          if (y->father) {
            if (y == y->father->right) y->father->right = x;
            else y->father->left = x;
          }
          x->right = y;
          y->father = x;
          update(y);
          update(x);
        }
        inline void splay(register node *x,const node *target=NULL) {
          register node *y;
          while (x->father != target) {
            y = x->father;
            if (x == y->left) {
              if (y->father != target && y == y->father->left) right_rotate(y);
              right_rotate(x);
            } else {
              if (y->father != target && y == y->father->right) left_rotate(y);
              left_rotate(x);
            }
          }
          if (!target) root = x;
        }
        inline node *find(register int index) {  
          register node *x = root;
          while(1) {
            if (!x) break;
            push_down(x);
            if (x->value < Left) {
              x = x->right;
            } else if (x->value > Right) x = x->left;
            else if (SIZE(x->left) == index - 1) break;
            else if (SIZE(x->left) >= index) x = x->left;
            else index -= SIZE(x->left) + 1, x = x->right;
          }
          return x;
        }
        inline void Order(register node *x) {
          if (!x) return;
          push_down(x);
          Order(x->left);
          if (x->value >= Left && x->value <= Right) List.push_back(x->value);
          Order(x->right);
        }
      public:
        splay_tree() {
          root = NULL;
        }
        inline void insert(const int &key) {
          register node *x = root, *y = NULL;
          while(1) {
            if (!x) break;
            y = x;
            if (x->value < key) x = x->right;
            else if (x->value > key) x = x->left;
          }
          x = new node(key);
          x->father = y;
          if (y) {
            if (x->value > y->value) y->right = x;
            else y->left = x;
          }
          if (!y) root = x;
          update(y);
          splay(x);
        }
        inline void init(const int &l,const int &r) {
          register node *x = new node(l - 1), *y = new node(r + 1);
          Left = l, Right = r;
          x->size = y->size = 0;
          x->right = y, y->father = x;
          root = x;
          left_node = x, right_node = y;
          for (register int i(l); i <= r; ++i) {
            insert(i);
          }
        }
        inline void reverse(const int &l, const int &r) {
          register node *x(l == Left ? left_node : find(l - 1)), 
                        *y(r == Right ? right_node : find(r + 1));
          splay(x), splay(y, x);
          if (y->left) y->left->delta ^= 1;
        }
        inline vector<int> c_list() {
          List.clear();
          Order(root->left);
          if (root->value >= Left && root->value <= Right) 
            List.push_back(root->value);
          Order(root->right);
          return List;
        }
    };
    splay_tree tree;
    int n, m, l, r;
    int main(int argc,char **argv) {
      Read(n), Read(m);
      tree.init(1, n);
      while (m--) {
        Read(l), Read(r);
        tree.reverse(l, r);
      }
      register vector<int> output_list = tree.c_list();
      for(register int i(0), list_size(output_list.size()); i < list_size; ++i) {
        printf("%d ", output_list[i]);
      }
      return 0;
    }
    
  • 相关阅读:
    redis全面解析
    SoapUI Pro Project Solution Collection-change the JDBC Request behavior
    SoapUI Pro Project Solution Collection-Test Step Object
    SoapUI Pro Project Solution Collection-access the soapui object
    SoapUI Pro Project Solution Collection –Easy develop Groovy Script to improve SoapUI ability
    Eclipse 个人使用配置
    Selenium 致命杀手(有关自动化的通病)
    Open-Source performance testing tools(From other site)
    麦当劳理论(转转转)
    java command line error opening registry key 'SoftwareJavaSoftJava Runtime Environment' java.dll
  • 原文地址:https://www.cnblogs.com/forth/p/9481756.html
Copyright © 2011-2022 走看看