牛客网多校训练第三场 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 ...
随机推荐
- bzoj 4942: [Noi2017]整数
Description Solution 加法减法可以分开考虑,如果只有加法的话,直接暴力进位复杂度是对的 询问的时候就是把两个二进制数做差,判断第 \(k\) 位的取值 实际上我们只需要判断 \(1 ...
- Java ConcurrentModificationException异常原因和解决方法(转)
摘自:http://www.cnblogs.com/dolphin0520/p/3933551.html#undefined 在前面一篇文章中提到,对Vector.ArrayList在迭代的时候如果同 ...
- Windows开启telnet命令
1.点击开始 → 运行 → 输入telnet,回车. 2.点击启用或关闭Windows功能 3.找到Telnet客户端,勾选,点击确认 4.搞定,测试一下 打开CMD,在出来的DOS界面里,输入tel ...
- PHP读取配置文件连接MySQL数据库
读取配置文件方法parse_ini_file($filepath [,$section]) 代码: conn.php <?php //连接数据库 //$conn =new mysqli('loc ...
- CXF - JAX-WS入门
相关dependency,我使用的版本是2.7.11: <dependency> <groupId>org.apache.cxf</groupId> <art ...
- java 并发 (四) ---- 并发容器
Hashmap 和 Concurrenthashmap Hashmap 不适合并发,应该使用ConcurrentHashMap . 这是很多人都知道的,但是为什么呢? 可以先看一下这两篇文章. JDK ...
- 用c+libcurl+PCRE写爬虫2--好用的正则表达式
写爬虫最重要的就是正则表达式的处理(爬出来的数据的筛选,清洗,过滤等操作). 通过一篇文章 http://blog.csdn.net/quaful/article/details/6460880 来确 ...
- 四层协议和Socket编程
<四层协议图> <Soclet编程模型图>
- 查询多表集合(union)、查询时建临时字段、查询时给字段设置默认值
() UNION () UNION (select i.create_time as time,i.investment_amount as amount,i.invest_state as stat ...
- Hibernate Annotation (Hibernate 注解)
简介: 传统上,Hibernate的配置依赖于外部 XML 文件:数据库映射被定义为一组 XML 映射文件,并且在启动时进行加载. 然而现在借助新的 Hibernate Annotation 库, ...