2018牛客网暑期ACM多校训练营(第三场) H - Shuffle Cards - [splay伸展树][区间移动][区间反转]
题目链接:https://www.nowcoder.com/acm/contest/141/C
空间限制:C/C++ 262144K,其他语言524288K
Special Judge, 64bit IO Format: %lld
题目描述
To prove that, Eddy wants to shuffle cards and tries to predict the final order of the cards. Actually, Eddy knows only one way to shuffle cards that is taking some middle consecutive cards and put them on the top of rest. When shuffling cards, Eddy just keeps repeating this procedure. After several rounds, Eddy has lost the track of the order of cards and believes that the assumption he made is wrong. As Eddy's friend, you are watching him doing such foolish thing and easily memorizes all the moves he done. Now, you are going to tell Eddy the final order of cards as a magic to surprise him.
Eddy has showed you at first that the cards are number from 1 to N from top to bottom.
For example, there are 5 cards and Eddy has done 1 shuffling. He takes out 2-nd card from top to 4-th card from top(indexed from 1) and put them on the top of rest cards. Then, the final order of cards from top will be [2,3,4,1,5].
输入描述:

输出描述:
Output one line contains N space-separated integers indicating the final order of the cards from top to bottom.
输入例子:
5 1
2 3
输出例子:
2 3 4 1 5
-->
输入
5 1
2 3
输出
2 3 4 1 5
输入
5 2
2 3
2 3
输出
3 4 1 2 5
输入
5 3
2 3
1 4
2 4
输出
3 4 1 5 2
题意:
给出一个1~n的数字序列,给出m次操作,每次操作会将以第p个数字为开始的连续s个数字拿出来放到整个序列的开头,求m次操作完成后的序列。
题解:
用splay来搞区间问题:https://www.cnblogs.com/dilthey/p/9379652.html#splay-5
可以直接先区间移动的函数,也可以使用三次区间反转来完成区间移动。
AC代码:
#include<bits/stdc++.h>
#define Key_value ch[ch[root][1]][0]
using namespace std;
const int maxn=1e5+; int n,m; /******************************** splay - st ********************************/
int root,nodecnt;
int par[maxn],ch[maxn][];
int key[maxn],size[maxn];
bool rev[maxn];
void NewNode(int &x,int p,int k)
{
x=++nodecnt;
par[x]=p;
ch[x][]=ch[x][]=;
key[x]=k;
size[x]=;
rev[x]=;
}
void Update_Rev(int x)
{
if(x==) return;
swap(ch[x][],ch[x][]);
rev[x]^=;
}
void Pushup(int x)
{
size[x]=size[ch[x][]]+size[ch[x][]]+;
}
void Pushdown(int x)
{
if(rev[x])
{
Update_Rev(ch[x][]);
Update_Rev(ch[x][]);
rev[x]=;
}
}
void Rotate(int x,int type) //旋转,0为左旋zag,1为右旋zig
{
int y=par[x];
Pushdown(y); Pushdown(x); //先把y的标记向下传递,再把x的标记往下传递
ch[y][!type]=ch[x][type]; par[ch[x][type]]=y;
if(par[y]) ch[par[y]][(ch[par[y]][]==y)]=x;
par[x]=par[y];
ch[x][type]=y; par[y]=x;
Pushup(y); Pushup(x);
}
void Splay(int x,int goal)
{
while(par[x]!=goal)
{
if(par[par[x]]==goal) Rotate(x,ch[par[x]][]==x); //左孩子zig,有孩子zag
else
{
Pushdown(par[par[x]]); Pushdown(par[x]); Pushdown(x);
int y=par[x];
int type=(ch[par[y]][]==y); //type=0,y是右孩子;type=1,y是左孩子
if(ch[y][type]==x)
{
Rotate(x,!type);
Rotate(x,type);
}
else
{
Rotate(y,type);
Rotate(x,type);
}
}
}
if(goal==) root=x;
}
int Get_Kth(int x,int k) //得到第k个节点
{
Pushdown(x);
int t=size[ch[x][]]+;
if(t==k) return x;
if(t>k) return Get_Kth(ch[x][],k);
else return Get_Kth(ch[x][],k-t);
}
int Get_Min(int x)
{
Pushdown(x);
while(ch[x][])
{
x=ch[x][];
Pushdown(x);
}
return x;
}
int Get_Max(int x)
{
Pushdown(x);
while(ch[x][])
{
x=ch[x][];
Pushdown(x);
}
return x;
}
void Build(int &x,int l,int r,int par) //建树,先建立中间结点,再建两端的方法
{
if(l>r) return;
int mid=(l+r)/;
NewNode(x,par,mid);
Build(ch[x][],l,mid-,x);
Build(ch[x][],mid+,r,x);
Pushup(x);
}
void Init() //初始化,前后各加一个空节点
{
root=nodecnt=;
ch[root][]=ch[root][]=size[root]=key[root]=par[root]=rev[root]=;
NewNode(root,,-); //头部加入一个空位
NewNode(ch[root][],root,-); //尾部加入一个空位
Build(Key_value,,n,ch[root][]);
Pushup(ch[root][]);
Pushup(root);
}
void Move(int l,int r,int p) //截取[l,r]放到位置p之后
{
Splay(Get_Kth(root,l-+),); //l的前驱l-1伸展到根
Splay(Get_Kth(root,r++),root); //r的后继r+1伸展到根的右孩子
int tmp=Key_value; //Key_value=ch[ch[root][1]][0]所统领的子树即[l,r]
Key_value=; //剥离[l,r]子树
Pushup(ch[root][]); Pushup(root);
Splay(Get_Kth(root,p++),); //p伸展到根
Splay(Get_Kth(root,p++),root); //p的后继p+1伸展到根的右孩子
Key_value=tmp; par[Key_value]=ch[root][]; //接上[l,r]子树
Pushup(ch[root][]); Pushup(root);
}
void Reverse(int l,int r) //反转[l,r]区间
{
Splay(Get_Kth(root,l-+),);
Splay(Get_Kth(root,r++),root);
Update_Rev(Key_value);
Pushup(ch[root][]);
Pushup(root);
}
/******************************** splay - ed ********************************/ int tot;
void Inorder(int x)
{
if(x==) return;
Pushdown(x);
Inorder(ch[x][]);
tot++;
if(tot>= && tot<=n+)
{
if(tot>) printf(" ");
printf("%d",key[x]);
}
Inorder(ch[x][]);
} int main()
{
scanf("%d%d",&n,&m);
Init(); for(int i=,st,ed;i<=m;i++)
{
scanf("%d%d",&st,&ed); ed=st+ed-; if(i%) Move(st,ed,);
else
{
Reverse(,st-);
Reverse(st,ed);
Reverse(,ed);
}
} Inorder(root);
printf("\n");
}
2018牛客网暑期ACM多校训练营(第三场) H - Shuffle Cards - [splay伸展树][区间移动][区间反转]的更多相关文章
- 2018牛客网暑期ACM多校训练营(第一场)J Different Integers(树状数组)
题意 给出一串数字以及q次查询,每次查询l,r],要求求出[1,l]和[r,n]的所有不相同的数字个数. 分析 先对数组进行倍增,变为两倍长,然后查询就变成一个完整的区间.离线处理,按r从小到大排序, ...
- 2018牛客网暑期ACM多校训练营(第二场)I- car ( 思维)
2018牛客网暑期ACM多校训练营(第二场)I- car 链接:https://ac.nowcoder.com/acm/contest/140/I来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 ...
- 2018牛客网暑期ACM多校训练营(第一场)D图同构,J
链接:https://www.nowcoder.com/acm/contest/139/D来源:牛客网 同构图:假设G=(V,E)和G1=(V1,E1)是两个图,如果存在一个双射m:V→V1,使得对所 ...
- 2018 牛客网暑期ACM多校训练营(第一场) E Removal (DP)
Removal 链接:https://ac.nowcoder.com/acm/contest/139/E来源:牛客网 题目描述 Bobo has a sequence of integers s1, ...
- 2018牛客网暑期ACM多校训练营(第二场)J Farm(树状数组)
题意 n*m的农场有若干种不同种类作物,如果作物接受了不同种类的肥料就会枯萎.现在进行t次施肥,每次对一个矩形区域施某种类的肥料.问最后枯萎的作物是多少. 分析 作者:xseventh链接:https ...
- 2018牛客网暑期ACM多校训练营(第一场)B Symmetric Matrix(思维+数列递推)
题意 给出一个矩阵,矩阵每行的和必须为2,且是一个主对称矩阵.问你大小为n的这样的合法矩阵有多少个. 分析 作者:美食不可负064链接:https://www.nowcoder.com/discuss ...
- 2018牛客网暑期ACM多校训练营(第二场) J - farm - [随机数哈希+二维树状数组]
题目链接:https://www.nowcoder.com/acm/contest/140/J 时间限制:C/C++ 4秒,其他语言8秒 空间限制:C/C++ 262144K,其他语言524288K ...
- 2018牛客网暑期ACM多校训练营(第二场) A - run - [DP]
题目链接:https://www.nowcoder.com/acm/contest/140/A 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 131072K,其他语言262144K ...
- 2018牛客网暑期ACM多校训练营(第一场) D - Two Graphs - [无向图同构]
题目链接:https://www.nowcoder.com/acm/contest/139/D 题目描述 Two undirected simple graphs and where are i ...
- 2018牛客网暑期ACM多校训练营(第一场) J - Different Integers - [莫队算法]
题目链接:https://www.nowcoder.com/acm/contest/139/J 题目描述 Given a sequence of integers a1, a2, ..., an a ...
随机推荐
- GOF---Java开发中的23种设计模式详解
表点 设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式 ...
- 【代码审计】DouPHP_v1.3代码执行漏洞分析
0x00 环境准备 DouPHP官网:http://www.douco.com/ 程序源码下载:http://down.douco.com/DouPHP_1.3_Release_20171002. ...
- bing搜索引擎子域名收集(Python脚本)
利用bing搜索引擎进行子域名收集,编写了一个简单的Python脚本,分享一下. #! /usr/bin/env python # _*_ coding:utf-8 _*_ import reques ...
- Python 管理 MySQL
Python MySQLdb 模块 Python pymysql 模块 Python SQLAlchemy 模块 Python ConfigParser 模块 Python 创建 MySQL 配置文件 ...
- ajax做省市联动
原理: 当select.jsp页面打开时,向服务器发送异步请求,得到所有省份的名称(文本数据).然后使用每个省份名称创建<option>,添加到<select name=”provi ...
- 【译】Kafka最佳实践 / Kafka Best Practices
本文来自于DataWorks Summit/Hadoop Summit上的<Apache Kafka最佳实践>分享,里面给出了很多关于Kafka的使用心得,非常值得一看,今推荐给大家. 硬 ...
- JTAG、JLink、ULINK、ST-LINK仿真器区别(转)
首先要了解一下JTAG. JTAG协议 JTAG(Joint Test Action Group,联合测试行动小组)是一种国际标准测试协议(IEEE 1149.1兼容),主要用于芯片内部测试.现在多数 ...
- 去掉a标签
需求: 去掉网页中所有的a标签 方法一: str.replace(/(<\/?a.*?>)|(<\/?span.*?>)/g, '');//str为要修改的那段文字 方法二: ...
- 深入浅出MFC——MFC多线程程序设计(七)
1. 从操作系统层面看线程——三个观念:模块(MDB).进程(PDB).线程(TDB) 2. “执行事实”发生在线程身上,而不在进程身上.也就是说,CPU调度单位是线程而非进程.调度器据以排序的,是每 ...
- 教你在windows下安装使用配置vim+gcc[转]
转自http://blog.163.com/lixiangqiu_9202/blog/static/535750372012461190722/ 一直在使用linux,但有时也会去虚拟机里的winxp ...