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
题意:FLIP操作就是区间的翻转,而CUT则是把某个区间移到某个点后面,本来打算用几次翻转来合成CUT函数,最后没有推出来。so借鉴kuangbin巨巨的作法
 #include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int maxn = 3e5+;
int siz[maxn],pre[maxn],ch[maxn][],rev[maxn],key[maxn];
int tot,root,n,m;
void NewNode(int &r,int father,int k)
{
r = ++tot;
pre[r] = father;
ch[r][] = ch[r][] = ;
key[r] = k;
siz[r] = ;
rev[r] = ;
}
void update_rev(int r)
{
if (!r)
return ;
swap(ch[r][],ch[r][]);
rev[r] ^= ;
}
void push_up(int r)
{
siz[r] = siz[ch[r][]] + siz[ch[r][]] + ;
}
void push_down(int r)
{
if (rev[r])
{
update_rev(ch[r][]);
update_rev(ch[r][]);
rev[r] = ;
}
}
void build(int &x,int l,int r,int father)
{
if (l > r)
return;
int mid = (l + r) >> ;
NewNode(x,father,mid);
build(ch[x][],l,mid-,x);
build(ch[x][],mid+,r,x);
push_up(x);
}
void init()
{
root = tot = ;
NewNode(root,,-);
NewNode(ch[root][],root,-);
build(ch[ch[root][]][],,n,ch[root][]);
push_up(ch[root][]);
push_up(root);
} void Rotate(int x,int kind)
{
int y = pre[x];
push_down(y);
push_down(x);
ch[y][!kind] = ch[x][kind];
pre[ch[x][kind]] = y;
if (pre[y])
ch[pre[y]][ch[pre[y]][] == y] = x;
pre[x] = pre[y];
ch[x][kind] = y;
pre[y] = x;
push_up(y);
} void Splay(int r,int goal)
{
push_down(r);
while (pre[r] != goal)
{
if (pre[pre[r]] == goal)
{
push_down(pre[r]);
push_down(r);
Rotate(r,ch[pre[r]][] == r);
}
else
{
int y = pre[r];
int kind = (ch[pre[y]][] == y);
push_down(pre[y]);
push_down(y);
push_down(r);
if (ch[y][kind] == r)
{
Rotate(y,!kind);
Rotate(r,!kind);
}
else
{
Rotate(r,kind);
Rotate(r,!kind);
}
}
}
push_up(r);
if (goal == )
root = r;
}
int Get_kth(int r,int k)
{
push_down(r);
int t = siz[ch[r][]] + ;
if (k == t)
return r;
if (k >= t)
return Get_kth(ch[r][],k-t);
else
return Get_kth(ch[r][],k);
}
void Reverse(int u,int v)
{
if (u > v)
return;
Splay(Get_kth(root,u),);
Splay(Get_kth(root,v+),root);
update_rev(ch[ch[root][]][]);
push_up(ch[root][]);
push_up(root);
}
void cut(int x,int y,int z) // cut函数本来想着用几次翻转来实现,推了半天没有推出来。so借鉴kuangbin巨巨的做法
{
Splay(Get_kth(root,x),);
Splay(Get_kth(root,y+),root);
int tmp = ch[ch[root][]][];
ch[ch[root][]][] = ;
push_up(ch[root][]);
push_up(root);
Splay(Get_kth(root,z+),);
Splay(Get_kth(root,z+),root);
ch[ch[root][]][] = tmp;
pre[ch[ch[root][]][]] = ch[root][];
push_up(ch[root][]);
push_up(root);
}
bool flag;
void dfs(int r)
{
if (!r)
return;
push_down(r);
dfs(ch[r][]);
if (r != - && key[r] != -)
{
printf(flag ? " %d":"%d",key[r]);
flag = ;
}
dfs(ch[r][]);
}
int main(void)
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
while (~scanf ("%d%d",&n,&m))
{
if (n < && m < )
break;
init();
for (int i = ; i < m; i++)
{
char op[];
int x,y,z;
scanf ("%s",op);
if (op[] == 'C')
{
scanf ("%d%d%d",&x,&y,&z);
cut(x,y,z);
}
else
{
scanf ("%d%d",&x,&y);
Reverse(x,y);
}
}
flag = ;
dfs(root);
printf("\n");
}
return ;
}

HDU--3487 Play with Chain (Splay伸展树)的更多相关文章

  1. HDU 3487 Play with Chain | Splay

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

  2. HDU 3487 Play with Chain(Splay)

    题目大意 给一个数列,初始时为 1, 2, 3, ..., n,现在有两种共 m 个操作 操作1. CUT a b c 表示把数列中第 a 个到第 b 个从原数列中删除得到一个新数列,并将它添加到新数 ...

  3. Splay伸展树学习笔记

    Splay伸展树 有篇Splay入门必看文章 —— CSDN链接 经典引文 空间效率:O(n) 时间效率:O(log n)插入.查找.删除 创造者:Daniel Sleator 和 Robert Ta ...

  4. 【学时总结】◆学时·VI◆ SPLAY伸展树

    ◆学时·VI◆ SPLAY伸展树 平衡树之多,学之不尽也…… ◇算法概述 二叉排序树的一种,自动平衡,由 Tarjan 提出并实现.得名于特有的 Splay 操作. Splay操作:将节点u通过单旋. ...

  5. hdu 3487 Play with Chain

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3487 YaoYao is fond of playing his chains. He has a c ...

  6. Splay 伸展树

    废话不说,有篇论文可供参考:杨思雨:<伸展树的基本操作与应用> Splay的好处可以快速分裂和合并. ===============================14.07.26更新== ...

  7. [Splay伸展树]splay树入门级教程

    首先声明,本教程的对象是完全没有接触过splay的OIer,大牛请右上角.. 首先引入一下splay的概念,他的中文名是伸展树,意思差不多就是可以随意翻转的二叉树 PS:百度百科中伸展树读作:BoGa ...

  8. Splay伸展树入门(单点操作,区间维护)附例题模板

    Pps:终于学会了伸展树的区间操作,做一个完整的总结,总结一下自己的伸展树的单点操作和区间维护,顺便给未来的自己总结复习用. splay是一种平衡树,[平均]操作复杂度O(nlogn).首先平衡树先是 ...

  9. Codeforces 675D Tree Construction Splay伸展树

    链接:https://codeforces.com/problemset/problem/675/D 题意: 给一个二叉搜索树,一开始为空,不断插入数字,每次插入之后,询问他的父亲节点的权值 题解: ...

随机推荐

  1. 关于C/C++函数指针声明的理解

    [前言] 由于最近对函数指针的理解比较模糊,所有又重新学习了一把关于函数指针的知识,参考了很多书籍和网上的文章.现在本人进行一下分享和总结.本文的其实只是整理和总结别人现有的文章,作为备用参考文档. ...

  2. [Qt] IP地址输入框实现

    封装了一个ip地址的输入框.网络上下载了份代码,找不到哪里的了.经过修改之后,尽力让它的行为和windows的IP地址输入框的行为看起来像些.代码如下: //ipaddredit.h #ifndef ...

  3. Python进阶(面向对象编程基础)(三)

    6.类属性和实例属性名字冲突怎么办 修改类属性会导致所有实例访问到的类属性全部都受影响,但是,如果在实例变量上修改类属性会发生什么问题呢? class Person(object): address ...

  4. ORACLE CASE WHEN 及 SELECT CASE WHEN的使用方法

    CASE 语句 CASE selector   WHEN value1 THEN action1;   WHEN value2 THEN action2;   WHEN value3 THEN act ...

  5. CCSpawn使用CCRepeatForever无效

    在使用CCSpawn中加入CCRepeatForever,但却无法使用CCRepeatForever的效果. CCActionInterval* action =(CCActionInterval*) ...

  6. Java程序性能分析工具Java VisualVM(Visual GC)—程序员必备利器

    VisualVM 是一款免费的\集成了多个JDK 命令行工具的可视化工具,它能为您提供强大的分析能力,对 Java 应用程序做性能分析和调优.这些功能包括生成和分析海量数据.跟踪内存泄漏.监控垃圾回收 ...

  7. HID class request.

    1.get report. 2.set report report request. Get report范例: 下面这张图是Host跟Device来要设备描述符. USB主机向设备控制器请求数据时, ...

  8. 为什么class中属性以空格分隔?

    1 div.contain .blue{color:blue;}/*后代选择器*/2 div.contain.blue{color:blue;} /*多类选择器*/ 以上两种规则分别应用的元素如下: ...

  9. Android material design support library -- CollapsingToolbarLayout简介

    本文是codetrick上material design support library教程的第三篇,主要讲的是CollapsingToolbarLayout的概念和应用方法. 原文链接:Materi ...

  10. Oracle 如何让别人能够连接到你的数据库

    Oracle 初步 --Oracle的一些关键字 i和g只是版本的代号,指oracle运用的技术i代表Internet就是互联网技术g代表grid就是网格技术现在出的最新版是c就是cloud也就是云技 ...