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. Spark SQL  inferSchema实现原理探微(Python)

    使用Spark SQL的基础是“注册”(Register)若干表,表的一个重要组成部分就是模式,Spark SQL提供两种选项供用户选择:   (1)applySchema     applySche ...

  2. 使用sqlhelper的简单增删改查

    一:所说的简单的三层构架,就是说没有业务逻辑层,将各层没有放到单独的项目中,解决方案如下: 二:form1.cs的详细代码 using System; using System.Collections ...

  3. unity3d Human skin real time rendering plus 真实模拟人皮实时渲染 plus篇

    最近逃课做游戏,逃的有几门都要停考了,呵呵呵,百忙之中不忘超炒冷饭,感觉之前的人皮效果还是不够好,又改进了一些东西 首先上图 放大看细节 显而易见的比上次的效果要好很多,此次我把模型用3dmax进行了 ...

  4. Android学习笔记(三)Application类简介

    每次运行APP时,Application类都保持实例化状态.与Activity不同,配置改变不会导致应用程序重启.通过继承Application类,可以完成一下3项工作: · 对Android运行时广 ...

  5. Hdu 2475-Box LCT,动态树

    Box Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  6. ACM2096

    #include<iostream> int main() { using namespace std; int a,b,count; cin>>count; while(co ...

  7. 《University Calculus》-chaper13-多重积分-二重积分的计算

    之前关于二重积分的笔记,介绍了二重积分概念的引入,但是对于它的计算方法(化为累次积分),介绍的较为模糊,它在<概率论基础教程>中一系列的推导中发挥着很重要的作用. 回想先前关于二重积分的几 ...

  8. HDU 3078 Network LCA

    题意:n个点 m个询问,下面一行是n 个点的权值 再下面n-1行是双向的边 然后m个询问:k u v 若k==0,则把u点的权值改为v,否则回答u->v之间最短路经过点的权值中  第k大的值是多 ...

  9. HTML5 File api 实现断点续传

    目前市场上大多数的网站的断点上传都是需要安装浏览器插件的,本文就针对高级浏览器的环境下,通过HTML5 File api实现断点上传进行说明 一.实现文件多选 HTML5的<input>新 ...

  10. [Javascript] Querying an Immutable.js Map()

    Learn how to query an Immutable.Map() using get, getIn, has, includes, find, first and last. These a ...