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里面的写法引用和不引用是不一样的。
昨天我两个都试了一下,今天就搞混了。。。。
 #include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <utility>
#include <iomanip>
#include <string>
#include <cmath>
#include <queue>
#include <assert.h>
#include <map>
#include <ctime>
#include <cstdlib>
#define LOCAL
const int MAXN = + ;
const int INF = ;
const int SIZE = ;
const int maxnode = 0x7fffffff + ;
using namespace std;
int M;
struct SPLAY{
struct Node{
int val, size;
bool turn;
Node *ch[], *parent; /*Node(){//暂时不要构造函数,节约时间
val = 0;
size = 0;
turn = 0;
parent = ch[0] = ch[1] = NULL;
}*/
int cmp(){
if (parent->ch[] == this) return ;
else return ;
}
//更新
}*root, *nil, _nil, mem[MAXN];
int tot; void pushdown(Node *&t){
if (t == nil) return;
if (t->turn){
Node *p;
p = t->ch[];
t->ch[] = t->ch[];
t->ch[] = p; if (t->ch[] != nil) t->ch[]->turn ^= ;
if (t->ch[] != nil) t->ch[]->turn ^= ;
t->turn = ;
}
}
void update(Node *&t){
t->size = ;
t->size += t->ch[]->size + t->ch[]->size;
}
Node* NEW(int val){
Node *p = &mem[tot++];
p->val = val;
p->size = ;
p->turn = ;
p->parent = p->ch[] = p->ch[] = nil;
return p;
}
void init(){
//哨兵初始化
nil = &_nil;
_nil.val = _nil.size = _nil.turn = ;
_nil.parent = _nil.ch[] = _nil.ch[] = nil; tot = ;
root = NEW(INF);
root->ch[] = NEW(INF);
root->ch[]->parent = root;
}
//1为右旋
/*void Rotate(Node *&t, int d){
Node *p = t->parent;
pushdown(p);
pushdown(t);
pushdown(t->ch[d]);
//t = p->ch[d ^ 1];这句话是废话,真正的一句一处
p->ch[d ^ 1] = t->ch[d];
if (t->ch[d] != nil) t->ch[d]->parent = p;
t->parent = p->parent;
if (p->parent != nil) p->ch[p->cmp()] = t;
t->ch[d] = p;
p->parent = t;
update(p);//注意这里为什么只要updatep是因为旋转是在伸展中使用的,因此t的更新在splay中
if (root == p) root = t;//换根
}*/
void Rotate(Node *t, int d){
Node *p = t->parent;//t的右旋对于p来说也是右旋
t = p->ch[d ^ ];
p->ch[d ^ ] = t->ch[d];
t->ch[d]->parent = p;
t->ch[d] = p;
t->parent = p->parent;
//注意,这里要更新的原因在于t并不是引用
if (t->parent != nil){
if (t->parent->ch[] == p) t->parent->ch[] = t;
else if (t->parent->ch[] == p) t->parent->ch[] = t;
}
p->parent = t;
if (t->parent == nil) root = t;
//不用换回去了...
update(p);
update(t);
//t->update();
}
void splay(Node *x, Node *y){
pushdown(x);
while (x->parent != y){
if (x->parent->parent == y){
Rotate(x, x->cmp() ^ );
break;
}else{
Rotate(x->parent, x->parent->cmp() ^ );
Rotate(x, x->cmp() ^ );
}
update(x);
}
update(x);//最后退出的update不要忘了
if (nil == y) root = x;
}
//找到第k小的数并将其伸展到y
void find(Node *y, int k){
Node *x = root;
while (){
//if (x == nil) break;//注意我已经在init中插入了两个数
pushdown(x);
int tmp = (x->ch[]->size);
if ((tmp + ) == k) break;
if (k <= tmp) x = x->ch[];
else k -= tmp + , x = x->ch[];
}
pushdown(x);
splay(x, y);
}
//在pos位置后面插入一个数val
void Insert(int pos, int val){
find(nil, pos + );
find(root, pos + );//时刻注意已经插入了两个INF
pushdown(root);
pushdown(root->ch[]);
Node *p = NEW(val), *t = root->ch[];
//一定要拆开!!不能放在ch[1]->[0]
p->ch[] = t;
t->parent = p;
root->ch[] = p;
p->parent = root;
splay(p, nil);
}
//剪掉a,b位置的数并接到c位置后面
void Cut(int a, int b, int c){
find(nil, a);
find(root, b + );
pushdown(root);
pushdown(root->ch[]); Node *p = root->ch[]->ch[];
root->ch[]->ch[] = nil;//剪掉
update(root->ch[]);///不要忘了更新
update(root); find(nil, c + );
find(root, c + );
pushdown(root);
pushdown(root->ch[]); root->ch[]->ch[] = p;
p->parent = root->ch[];
update(root->ch[]);
update(root);
splay(p, nil);
}
void Reverse(int l, int r){
find(nil, l);
find(root, r + );
//print(root);
root->ch[]->ch[]->turn ^= ;
Node *p = root->ch[]->ch[];
splay(p, nil);
}
void print(Node *t){
if (t == nil) return;
pushdown(t);
print(t->ch[]);
if (t->val != INF){
if (M != ) {printf("%d ", t->val);M--;}
else printf("%d", t->val);
}
print(t->ch[]);
}
}A;
int n, m; void init(){
A.init();
//scanf("%d%d", &n, &m);
for (int i = ; i < n; i++){
A.Insert(i, i + );
}
//A.print(A.root);
}
void work(){
for (int i = ; i <= m; i++){
char str[];
scanf("%s", str);
if (str[] == 'C'){
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
A.Cut(a, b, c);
}else{
int l, r;
scanf("%d%d", &l, &r);
A.Reverse(l, r);
}
//A.print(A.root);
}
M = n;
A.print(A.root);
} int main(){ while (scanf("%d%d", &n, &m)){
if (n == - && m == -) break;
init();
//A.find(A.nil, 3);
//printf("%d", A.root->size);
work();
printf("\n");
}
return ;
}

【HDU3487】【splay分裂合并】Play with Chain的更多相关文章

  1. bzoj3223 文艺平衡树 (treap or splay分裂+合并)

    3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 3313  Solved: 1883 [Submit][S ...

  2. hdu3487 splay树

    Play with Chain Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  3. 【BZOJ-2809】dispatching派遣 Splay + 启发式合并

    2809: [Apio2012]dispatching Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2334  Solved: 1192[Submi ...

  4. 【BZOJ-2733】永无乡 Splay+启发式合并

    2733: [HNOI2012]永无乡 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2048  Solved: 1078[Submit][Statu ...

  5. BZOJ2733 永无乡【splay启发式合并】

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  6. BZOJ 2733: [HNOI2012]永无乡 [splay启发式合并]

    2733: [HNOI2012]永无乡 题意:加边,询问一个连通块中k小值 终于写了一下splay启发式合并 本题直接splay上一个节点对应图上一个点就可以了 并查集维护连通性 合并的时候,把siz ...

  7. bzoj2733: [HNOI2012]永无乡(splay+启发式合并/线段树合并)

    这题之前写过线段树合并,今天复习Splay的时候想起这题,打算写一次Splay+启发式合并. 好爽!!! 写了长长的代码(其实也不长),只凭着下午的一点记忆(没背板子...),调了好久好久,过了样例, ...

  8. 【BZOJ2733】永无乡[HNOI2012](splay启发式合并or线段树合并)

    题目大意:给你一些点,修改是在在两个点之间连一条无向边,查询时求某个点能走到的点中重要度第k大的点.题目中给定的是每个节点的排名,所以实际上是求第k小:题目求的是编号,不是重要度的排名.我一开始差点被 ...

  9. 算法复习——splay+启发式合并(bzoj2733-永无乡)

    题目: Description 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通 ...

随机推荐

  1. Linux驱动的两种加载方式过程分析

    一.概念简述 在Linux下可以通过两种方式加载驱动程序:静态加载和动态加载. 静态加载就是把驱动程序直接编译进内核,系统启动后可以直接调用.静态加载的缺点是调试起来比较麻烦,每次修改一个地方都要重新 ...

  2. Distinct Subsequences——Leetcode

    Given a string S and a string T, count the number of distinct subsequences of T in S. A subsequence ...

  3. Myeclipse在启动Tomcat服务器的时候总是进入debug视图的解决方法

    最近调试程序,由于出现过一些错误,在调试的时候,更改过一些东西,但是后来在myeclipse下启动Tomcat服务器的时候,自动的跳入到debug视图了(以前是一启动Tomcat服务器后,直接就加载t ...

  4. 长沙Uber优步司机奖励政策(1月18日~1月24日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  5. Java多线程实现简单的售票程序

    设计一个多线程程序如下:设计一个火车售票模拟程序.假如火车站要有100张火车票要卖出,现在有5个售票点同时售票,用5个线程模拟这5个售票点的售票情况 1.要求打印出每个售票点所卖出的票号 2.各售票点 ...

  6. 【设计模式 - 16】之迭代器模式(Iterator)

    1      模式简介 迭代器模式是JAVA中非常常用的模式,List.Map.Set等常见集合中都封装了迭代器Iterator. 迭代器模式的介绍: 迭代器模式用于顺序访问集合对象中的元素,而不需要 ...

  7. 【Android - 框架】之GreenDao的使用

    上一篇博客([Android - 框架]之ORMLite的使用)中介绍了ORMLite的基本使用,今天我们来研究以下GreenDao的使用. GreenDao和ORMLite一样,都是基于ORM(Ob ...

  8. Python基础知识--列表和集合

    列表:有序性,可以存放任意类型的对象,通过索引访问,可以分片操作 >>> L = ['id', 1000, 'scd', 1000, 'scd'] >>> L [' ...

  9. IAP内购 返回的产品数量为0

    上个月搞IAP,提交到appstore审核被拒,根据附件截图 可以知道是请求产品信息的时候,产品数量返回0了. 返回产品数量为0 要么是Itunes Connect 里面的Contracts Tax ...

  10. VMware-workstation-full-12.0.1-3160714

    https://download3.vmware.com/software/wkst/file/VMware-workstation-full-12.0.1-3160714.exe 5A02H-AU2 ...