zoukankan      html  css  js  c++  java
  • 【HDU3487】【splay*合并】Play with Chain

    Problem Description
    YaoYao is fond of playing his chains. He has a chain containing n diamonds on it. Diamonds are numbered from 1 to n.
    At first, the diamonds on the chain is a sequence: 1, 2, 3, …, n.
    He will perform two types of operations:
    CUT a b c: He will first cut down the chain from the ath diamond to the bth diamond. And then insert it after the cth diamond on the remaining chain.
    For example, if n=8, the chain is: 1 2 3 4 5 6 7 8; We perform “CUT 3 5 4”, Then we first cut down 3 4 5, and the remaining chain would be: 1 2 6 7 8. Then we insert “3 4 5” into the chain before 5th diamond, the chain turns out to be: 1 2 6 7 3 4 5 8.

    FLIP a b: We first cut down the chain from the ath diamond to the bth diamond. Then reverse the chain and put them back to the original position.
    For example, if we perform “FLIP 2 6” on the chain: 1 2 6 7 3 4 5 8. The chain will turn out to be: 1 4 3 7 6 2 5 8

    He wants to know what the chain looks like after perform m operations. Could you help him? 
     
    Input
    There will be multiple test cases in a test data. 
    For each test case, the first line contains two numbers: n and m (1≤n, m≤3*100000), indicating the total number of diamonds on the chain and the number of operations respectively.
    Then m lines follow, each line contains one operation. The command is like this:
    CUT a b c // Means a CUT operation, 1 ≤ a ≤ b ≤ n, 0≤ c ≤ n-(b-a+1).
    FLIP a b    // Means a FLIP operation, 1 ≤ a < b ≤ n.
    The input ends up with two negative numbers, which should not be processed as a case.
     
    Output
    For each test case, you should print a line with n numbers. The ith number is the number of the ith diamond on the chain.
     
    Sample Input
    8 2 CUT 3 5 4 FLIP 2 6 -1 -1
     
    Sample Output
    1 4 3 7 6 2 5 8
     
    Source
    【分析】
    果断被指针引用坑.......
    调了一个半小时,本来想复习一下昨天的内容,结果被虐了。。
    感觉pushdown和update出现的地方有些奇怪.
    还有就是rotate里面的写法引用和不引用是不一样的。
    昨天我两个都试了一下,今天就搞混了。。。。
      1 #include <iostream>
      2 #include <cstdio>
      3 #include <algorithm>
      4 #include <cstring>
      5 #include <vector>
      6 #include <utility>
      7 #include <iomanip>
      8 #include <string>
      9 #include <cmath>
     10 #include <queue>
     11 #include <assert.h>
     12 #include <map>
     13 #include <ctime>
     14 #include <cstdlib>
     15 #define LOCAL
     16 const int MAXN = 500000 + 10;
     17 const int INF = 100000000;
     18 const int SIZE = 450;
     19 const int maxnode =  0x7fffffff + 10;
     20 using namespace std;
     21 int M;
     22 struct SPLAY{
     23        struct Node{
     24               int val, size;
     25               bool turn;
     26               Node *ch[2], *parent;
     27               
     28               /*Node(){//暂时不要构造函数,节约时间 
     29                      val = 0;
     30                      size = 0;
     31                      turn = 0;
     32                      parent = ch[0] = ch[1] = NULL;
     33               }*/
     34               int cmp(){
     35                   if (parent->ch[0] == this) return 0;
     36                   else return 1;
     37               }
     38               //更新 
     39        }*root, *nil, _nil, mem[MAXN];
     40        int tot;
     41 
     42        void pushdown(Node *&t){
     43             if (t == nil) return;
     44             if (t->turn){
     45                Node *p;
     46                p = t->ch[0];
     47                t->ch[0] = t->ch[1];
     48                t->ch[1] = p;
     49                       
     50                if (t->ch[0] != nil) t->ch[0]->turn ^= 1;
     51                if (t->ch[1] != nil) t->ch[1]->turn ^= 1;
     52                t->turn = 0;
     53             }
     54        }
     55        void update(Node *&t){
     56             t->size = 1;
     57             t->size += t->ch[0]->size + t->ch[1]->size;
     58        }
     59        Node* NEW(int val){
     60              Node *p = &mem[tot++];
     61              p->val = val;
     62              p->size = 1;
     63              p->turn = 0;
     64              p->parent = p->ch[0] = p->ch[1] = nil; 
     65              return p;
     66        }
     67        void init(){
     68             //哨兵初始化 
     69             nil = &_nil;
     70             _nil.val = _nil.size = _nil.turn = 0;
     71             _nil.parent = _nil.ch[0] = _nil.ch[1] = nil;
     72             
     73             tot = 0;
     74             root = NEW(INF);
     75             root->ch[1] = NEW(INF);
     76             root->ch[1]->parent  = root;
     77        }
     78        //1为右旋 
     79        /*void Rotate(Node *&t, int d){
     80             Node *p = t->parent;
     81             pushdown(p);
     82             pushdown(t);
     83             pushdown(t->ch[d]);
     84             //t = p->ch[d ^ 1];这句话是废话,真正的一句一处 
     85             p->ch[d ^ 1] = t->ch[d];
     86             if (t->ch[d] != nil) t->ch[d]->parent = p;
     87             t->parent = p->parent;
     88             if (p->parent != nil) p->ch[p->cmp()] = t;
     89             t->ch[d] = p;
     90             p->parent = t;
     91             update(p);//注意这里为什么只要updatep是因为旋转是在伸展中使用的,因此t的更新在splay中 
     92             if (root == p) root = t;//换根 
     93        }*/
     94        void Rotate(Node *t, int d){
     95             Node *p = t->parent;//t的右旋对于p来说也是右旋
     96             t = p->ch[d ^ 1];
     97             p->ch[d ^ 1] = t->ch[d];
     98             t->ch[d]->parent = p;
     99             t->ch[d] = p;
    100             t->parent = p->parent;
    101             //注意,这里要更新的原因在于t并不是引用 
    102             if (t->parent != nil){
    103                if (t->parent->ch[0] == p) t->parent->ch[0] = t;
    104                else if (t->parent->ch[1] == p)  t->parent->ch[1] = t;
    105             }
    106             p->parent = t;
    107             if (t->parent == nil) root = t;
    108             //不用换回去了... 
    109             update(p);
    110             update(t);
    111             //t->update();
    112        }
    113        void splay(Node *x, Node *y){
    114             pushdown(x);
    115             while (x->parent != y){
    116                   if (x->parent->parent == y){
    117                      Rotate(x, x->cmp() ^ 1);
    118                      break;
    119                   }else{
    120                      Rotate(x->parent, x->parent->cmp() ^ 1);
    121                      Rotate(x, x->cmp() ^ 1);
    122                   }
    123                   update(x);
    124             }
    125             update(x);//最后退出的update不要忘了 
    126             if (nil == y) root = x;
    127        }
    128        //找到第k小的数并将其伸展到y 
    129        void find(Node *y, int k){
    130             Node *x = root;
    131             while (1){
    132                   //if (x == nil) break;//注意我已经在init中插入了两个数 
    133                   pushdown(x);
    134                   int tmp = (x->ch[0]->size);
    135                   if ((tmp + 1) == k) break;
    136                   if (k <= tmp) x = x->ch[0];
    137                   else k -= tmp + 1, x = x->ch[1]; 
    138             }
    139             pushdown(x);
    140             splay(x, y);
    141        }
    142        //在pos位置后面插入一个数val 
    143        void Insert(int pos, int val){
    144             find(nil, pos + 1);
    145             find(root, pos + 2);//时刻注意已经插入了两个INF 
    146             pushdown(root);
    147             pushdown(root->ch[1]);
    148             Node *p = NEW(val), *t = root->ch[1];
    149             //一定要拆开!!不能放在ch[1]->[0] 
    150             p->ch[1] = t;
    151             t->parent = p;
    152             root->ch[1] = p;
    153             p->parent = root;
    154             splay(p, nil);
    155        }
    156        //剪掉a,b位置的数并接到c位置后面 
    157        void Cut(int a, int b, int c){
    158             find(nil, a);
    159             find(root, b + 2);
    160             pushdown(root);
    161             pushdown(root->ch[1]);
    162             
    163             Node *p = root->ch[1]->ch[0];
    164             root->ch[1]->ch[0] = nil;//剪掉
    165             update(root->ch[1]);///不要忘了更新 
    166             update(root);
    167             
    168             find(nil, c + 1);
    169             find(root, c + 2);
    170             pushdown(root);
    171             pushdown(root->ch[1]);
    172             
    173             root->ch[1]->ch[0] = p;
    174             p->parent = root->ch[1];
    175             update(root->ch[1]);
    176             update(root);
    177             splay(p, nil); 
    178        }
    179        void Reverse(int l, int r){
    180             find(nil, l);
    181             find(root, r + 2);
    182             //print(root);
    183             root->ch[1]->ch[0]->turn ^= 1;
    184             Node *p = root->ch[1]->ch[0];
    185             splay(p, nil);
    186        }
    187        void print(Node *t){
    188             if (t == nil) return;
    189             pushdown(t);
    190             print(t->ch[0]);
    191             if (t->val != INF){
    192                if (M != 1) {printf("%d ", t->val);M--;}
    193                else printf("%d", t->val);
    194             }
    195             print(t->ch[1]);
    196        }
    197 }A;
    198 int n, m;
    199 
    200 void init(){
    201      A.init();
    202      //scanf("%d%d", &n, &m);
    203      for (int i = 0; i < n; i++){
    204          A.Insert(i, i + 1);
    205      }
    206      //A.print(A.root);
    207 }
    208 void work(){
    209      for (int i = 1; i <= m; i++){
    210          char str[10];
    211          scanf("%s", str);
    212          if (str[0] == 'C'){
    213             int a, b, c;
    214             scanf("%d%d%d", &a, &b, &c);
    215             A.Cut(a, b, c);
    216          }else{
    217             int l, r;
    218             scanf("%d%d", &l, &r);
    219             A.Reverse(l, r);
    220          }
    221          //A.print(A.root);
    222      }
    223      M = n;
    224      A.print(A.root);
    225 }
    226 
    227 int main(){
    228     
    229     while (scanf("%d%d", &n, &m)){
    230           if (n == -1 && m == -1) break;
    231           init();
    232           //A.find(A.nil, 3);
    233           //printf("%d", A.root->size);
    234           work();
    235           printf("
    ");
    236     }
    237     return 0;
    238 }
    View Code
  • 相关阅读:
    arduino编程基础之--程序 元素
    arduino编程基础之--环境搭建
    C语言高手之路--目录
    生活中的数据结构
    Manjaro-KDE配置全攻略转
    多线程程序的奇怪问题记录
    manjaro安装openmv ide
    Linux进程数据结构详解
    Linux ps aux指令詳解--转
    记一次粗心大意的代码错误
  • 原文地址:https://www.cnblogs.com/hoskey/p/4331616.html
Copyright © 2011-2022 走看看