牛客网多校训练第三场 C - Shuffle Cards(Splay / rope)
链接:
https://www.nowcoder.com/acm/contest/141/C
题意:
给出一个n个元素的序列(1,2,...,n)和m个操作(1≤n,m≤1e5),
每个操作给出两个数p和s(1≤pi≤n,1≤si≤n-pi+1),表示把序列中从p开始的s个数移到最前面,
例如序列[1,2,3,4,5]在p=2,s=3时变成序列[2,3,4,1,5],输出最后的序列。
分析:
对于每个操作,直接把序列拆成三个部分,再重新拼接一下就行。
可以用Splay或rope来快速完成这个操作。
代码:
Splay版
#include <cstdio> /// 元素编号从1开始,使用前要初始化(init)
template<typename type> // 元素类型
class SplaySequence {
public:
struct Node {
Node *ch[]; // 左右子树
int s; // 结点数
type v; // 值
bool flip; // 反转标记
int cmp(int k) const {
int d = k - ch[]->s;
if(d == ) return -;
return d <= ? : ;
}
void maintain() {
s = ch[]->s + ch[]->s + ;
}
void pushdown() {
if(!flip) return;
flip = false;
Node* t = ch[]; ch[] = ch[]; ch[] = t;
ch[]->flip ^= ;
ch[]->flip ^= ;
}
};
Node* root; // 根结点
// 将序列分裂成s[1...k]和s[k+1...o->s],分别放于left和right
void split(Node* o, int k, Node* &left, Node* &right) {
if(k <= ) {
left = null;
right = o;
return;
}
splay(o, k);
left = o;
right = o->ch[];
o->ch[] = null;
left->maintain();
}
// 合并left和right。
Node* merge(Node* left, Node* right) {
if(left == null) return right;
splay(left, left->s);
left->ch[] = right;
left->maintain();
return left;
}
// 在第k个元素之后插入v
void insert(int k, type v) {
Node *left, *right, *mid = newNode();
mid->ch[] = mid->ch[] = null;
mid->s = ;
mid->v = v;
mid->flip = false;
split(root, k, left, right);
root = merge(merge(left, mid), right);
}
// 删除第k个元素
void erase(int k) {
Node *left, *right, *mid, *o;
split(root, k-, left, o);
split(o, , mid, right);
root = merge(left, right);
delNode(mid);
}
// 将第L...R个元素反转
void reverse(int L, int R) {
Node *left, *right, *mid, *o;
split(root, L-, left, o);
split(o, R-L+, mid, right);
mid->flip ^= ;
root = merge(merge(left, mid), right);
}
// 返回第k个元素
Node* kth(int k) {
Node* o = root;
while(o != null) {
int d = o->cmp(k);
if(d == -) return o;
if(d == ) k -= o->ch[]->s + ;
o = o->ch[d];
}
return null;
}
// 读取第k个元素
type operator[](int k) {
return kth(k)->v;
}
// 返回元素个数
int size() {
return root->s;
}
// 初始化、清空序列
void init() {
for(int i = ; i < MAXS; i++) stk[i] = &mem[i];
top = MAXS - ;
null = newNode();
null->s = ;
root = null;
}
// 中序遍历输出整个序列
void print(Node* o) {
if(o == null) return;
o->pushdown();
print(o->ch[]);
printf("%d ", o->v);
print(o->ch[]);
}
private:
static const int MAXS = 1e6 + ; // 最大结点数
Node* null;
int top;
Node* stk[MAXS];
Node mem[MAXS];
void rotate(Node* &o, int d) {
Node* k = o->ch[d^];
o->ch[d^] = k->ch[d];
k->ch[d] = o;
o->maintain();
k->maintain();
o = k;
}
void splay(Node* &o, int k) {
o->pushdown();
int d = o->cmp(k);
if(d == -) return;
if(d == ) k -= o->ch[]->s + ;
Node* p = o->ch[d];
p->pushdown();
int d2 = p->cmp(k);
int k2 = (d2 == ? k : k - p->ch[]->s - );
if(d2 != -) {
splay(p->ch[d2], k2);
if(d == d2) rotate(o, d^);
else rotate(o->ch[d], d);
}
rotate(o, d^);
}
Node* newNode() {
return stk[top--];
}
void delNode(Node* o) {
stk[++top] = o;
}
}; SplaySequence<int> ss; int main() {
int n, m;
scanf("%d%d", &n, &m);
ss.init();
for(int i = ; i <= n; i++) ss.insert(ss.size(), i);
for(int p, s, i = ; i < m; i++) {
scanf("%d%d", &p, &s);
SplaySequence<int>::Node *left, *mid, *right, *o;
ss.split(ss.root, p-, left, o);
ss.split(o, s, mid, right);
ss.root = ss.merge(ss.merge(mid, left), right);
}
ss.print(ss.root);
return ;
}
rope版
#include <cstdio>
#include <ext/rope>
using namespace __gnu_cxx; rope<int> r; int main() {
int n, m;
scanf("%d%d", &n, &m);
for(int i = ; i <= n; i++) r.push_back(i);
for(int p, s, i = ; i < m; i++) {
scanf("%d%d", &p, &s);
p--;
r = r.substr(p, s) + r.substr(, p) + r.substr(p+s, n-p-s);
}
for(int i = ; i < n; i++) printf("%d ", r[i]);
return ;
} /*
r.push_back(x); // 在末尾添加x
r.insert(pos, x); // 在pos插入x
r.erase(pos, x); // 从pos开始删除x个
r.copy(pos, len, x); // 从pos开始到pos+len为止用x代替
r.replace(pos, x); // 从pos开始换成x
r.substr(pos, x); // 提取pos开始x个
r.at(x) / [x]; // 访问第x个元素
时间复杂度为n*(n^0.5)
*/
牛客网多校训练第三场 C - Shuffle Cards(Splay / rope)的更多相关文章
- 牛客网多校训练第三场 A - PACM Team(01背包变形 + 记录方案)
链接: https://www.nowcoder.com/acm/contest/141/A 题意: 有n(1≤n≤36)个物品,每个物品有四种代价pi,ai,ci,mi,价值为gi(0≤pi,ai, ...
- 牛客网多校训练第四场C sequence
(牛客场场有笛卡尔树,场场都不会用笛卡尔树...自闭,补题心得) 题目链接:https://ac.nowcoder.com/acm/contest/884/C 题意:给出两个序列a,b,求max{mi ...
- 牛客网2018暑期训练 第三场 a题
#include <bits/stdc++.h> using namespace std; vector<int> path; ; short dp[maxn][maxn][m ...
- 牛客网多校训练第八场A All one Matrix
题目链接:https://ac.nowcoder.com/acm/contest/888/A 题意:求出有多少个不被包含的全1子矩阵 解题思路:首先对列做处理,维护每个位置向上1的个数,然后我们从最后 ...
- 牛客网多校训练第二场D Kth Minimum Clique
链接:https://ac.nowcoder.com/acm/contest/882/D来源:牛客网 Given a vertex-weighted graph with N vertices, fi ...
- 牛客网多校赛第9场 E-Music Game【概率期望】【逆元】
链接:https://www.nowcoder.com/acm/contest/147/E 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524 ...
- 牛客网多校赛第七场J--Sudoku Subrectangle
链接:https://www.nowcoder.com/acm/contest/145/J 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言6553 ...
- 牛客网多校赛第七场--C Bit Compression【位运算】【暴力】
链接:https://www.nowcoder.com/acm/contest/145/C 来源:牛客网 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 262144K,其他语言524 ...
- 牛客网多校赛第七场A--Minimum Cost Perfect Matching【位运算】【规律】
链接:https://www.nowcoder.com/acm/contest/145/A 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524 ...
随机推荐
- EPPlus导入导出不占用进程
导入: using (ExcelPackage package = new ExcelPackage(new FileStream(openFile.FileName, FileMode.Open, ...
- Eclipse 工具栏无法移动的解决办法
升级到Juno后发现工具栏有些乱 而且无法拖动,试了下http://blog.csdn.net/cxx504659987/article/details/38532599的方法 发现配置文件里没有文中 ...
- Java - 谨慎覆盖clone
覆盖clone时需要实现Cloneable接口,Cloneable并没有定义任何方法. 那Cloneable的意义是什么? 如果一个类实现了Clonable,Object的clone方法就可以返回该对 ...
- Spring Cloud实战之初级入门(五)— 配置中心服务化与配置实时刷新
目录 1.环境介绍 2.配置中心服务化 2.1 改造mirco-service-spring-config 2.2 改造mirco-service-provider.mirco-service-con ...
- 流畅的python和cookbook学习笔记(五)
1.随机选择 python中生成随机数使用random模块. 1.从序列中随机挑选元素,使用random.choice() >>> import random >>> ...
- 读EntityFramework.DynamicFilters源码_心得_单元测试03
上个星期我们只是显示了一个示例,怎么在EF的框架内,注入我们拓展的动态过滤器 第一步:安装EntityFramework.DynamicFilters 第二步:重写OnModelCreating方法 ...
- 第十三章.MySQL数据库与JDBC编程(下)
JDBC的典型用法: JDBC4.2常用接口和类简介: DriverManager:用于管理JDBC驱动的服务类,程序中使用该类的主要功能是获取Connection对象,该类包含如下方法: publi ...
- 2048小游戏4X4C语言
*/ #include<stdio.h> #include<stdlib.h> #include<conio.h> #include<time.h> v ...
- js中map和python中的map
js 中的map: 由于map()方法定义在JavaScript的Array中,我们调用Array的map()方法,传入我们自己的函数,就得到了一个新的Array作为结果: function pow( ...
- JavaScript有限状态机实现方式
阮一峰博客 http://www.ruanyifeng.com/blog/2013/09/finite-state_machine_for_javascript.html 开源实现库(javascri ...