牛客网多校训练第三场 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 ...
随机推荐
- uploadify 图片上传
遇到的问题总结: 1.//图片排序 $("#pics").sortable(); 2.//上传的文件对象名,与后台所传参数名保持一致,最初因为这个名称错误浪费了许久时间 fileO ...
- Consul 遇到的坑
均衡负载时调用的地址 spring.cloud.consul.discovery.service-name= 当A服务调用B服务时,可以转发到注册中心进行转发调用, 应该使用这个地址,这一点和eure ...
- Redis单机数据迁移至Sentinel集群
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://mave ...
- oauth2.0授权码模式详解
授权码模式原理 授权码模式(authorization code)是功能最完整.流程最严密的授权模式.它的特点就是通过客户端的后台服务器,与"服务提供商"的认证服务器进行互动. 它 ...
- lincode 题目记录5
Course Schedule 安排课表 Frog Jump 最长回文字符串长度 Course Schedule 选课方案问题,题目说的很清楚了就是bfs或者dfs,然后加个字典优化,弄了好久没 ...
- maven(04)--一个简单的项目
简单介绍 一个maven项目,使用hibernate框架,实现向mysql数据库中添加和获取操作,其他操作也是类似 如果你没有hibernate,那么也不要紧,这里主要介绍如何在一个maven项目中引 ...
- DB DBS 和DBMS区别
DB:是指datebase(数据库) DBS:是指datebase systerm (数据库系统) DBMS:是指datebase mangement systerm(数据库管理系统)区别:数据库 ...
- 【小记录】关于dojo中的on事件
今天碰到一个现象,若是一个函数中存在一个on事件(例如点击事件),在该函数连续触发两次之后在去触发里面的on事件,会发现改时间所对应的函数被调用了两次,若父函数被连续触发N次后再取触发on事件,其对应 ...
- Jquery ajax动态更新下拉列表的内容
$("#book_id").change(function(){ $book_id=$(this).children('option:selected').val(); //ale ...
- Postfix的工作原理
传统的Sendmail将所有功能都集中在同一个程序里,这种结构我们称之为“单体式设计”(monolithic).Postfix采用专职负责的策略,不同的功能分别交由不同的专门程序处理,这种结构称为“模 ...