[CQOI2014]排序机械臂
嘟嘟嘟
最近复习复习平衡树,然后又体会到了那种感觉:“写代码半小时,debug一下午”。
这题其实就是让你搞一个数据结构,支持一下操作:
1.区间翻转。
2.查询区间最小值所在位置。
刚开始我想错了,想直接维护点权最小的点所在位置,但是这样旋转的时候就彻底的乱了,不知咋维护。
后来有一个不错的主意:维护最小值所在的结点编号,查询的时候旋转到根,则左子树大小就是位置。
看起来很简单,但其实有一下坑点:
1.pushup特别容易写错。首先得把当前节点的所有值都初始化成自己,比如Min设为自己的权值,所在结点编号pos设为自己的编号……我因为这个debug了好半天。
2.我们维护的是节点编号,所以查询的时候哦并不是从根一路找下来的。所以splay之前必须把到根的路径上的所有点都pushdown一遍,就跟lct一样。
还是菜啊。
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define enter puts("")
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define In inline
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-8;
const int maxn = 1e5 + 5;
inline ll read()
{
ll ans = 0;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) last = ch, ch = getchar();
while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
if(last == '-') ans = -ans;
return ans;
}
inline void write(ll x)
{
if(x < 0) x = -x, putchar('-');
if(x >= 10) write(x / 10);
putchar(x % 10 + '0');
}
int n, a[maxn];
struct Tree
{
int ch[2], fa, siz;
int val, id;
int sec, Min, pos;
bool rev;
In bool operator < (const Tree& oth)const
{
if(Min ^ oth.Min) return Min < oth.Min;
return sec < oth.sec;
}
}t[maxn];
int root, tcnt = 0;
In void Rev(int now)
{
swap(t[now].ch[0], t[now].ch[1]);
t[now].rev ^= 1;
}
In void pushdown(int now)
{
if(t[now].rev)
{
if(t[now].ch[0]) Rev(t[now].ch[0]);
if(t[now].ch[1]) Rev(t[now].ch[1]);
t[now].rev = 0;
}
}
In void change(int now, int son)
{
t[now].Min = t[son].Min;
t[now].sec = t[son].sec;
t[now].pos = t[son].pos;
}
In void pushup(int now)
{
t[now].siz = 1;
t[now].Min = t[now].val; t[now].sec = t[now].id;
t[now].pos = now;
if(t[now].ch[0])
{
t[now].siz += t[t[now].ch[0]].siz;
if(t[t[now].ch[0]] < t[now]) change(now, t[now].ch[0]);
}
if(t[now].ch[1])
{
t[now].siz += t[t[now].ch[1]].siz;
if(t[t[now].ch[1]] < t[now]) change(now, t[now].ch[1]);
}
}
In void rotate(int x)
{
int y = t[x].fa, z = t[y].fa, k = (t[y].ch[1] == x);
t[z].ch[t[z].ch[1] == y] = x; t[x].fa = z;
t[y].ch[k] = t[x].ch[k ^ 1]; t[t[x].ch[k ^ 1]].fa = y;
t[x].ch[k ^ 1] = y; t[y].fa = x;
pushup(y); pushup(x);
}
int st[maxn], top = 0;
In void splay(int x, int s)
{
st[top = 1] = x;
int y = x;
while(t[y].fa) st[++top] = y = t[y].fa;
while(top--) pushdown(st[top]);
while(t[x].fa ^ s)
{
int y = t[x].fa, z = t[y].fa;
if(z ^ s) rotate(((t[y].ch[0] == x) ^ (t[z].ch[0] == y)) ? x : y);
rotate(x);
}
if(!s) root = x;
}
In void build(int& now, int L, int R, int _f)
{
if(L > R) return;
int mid = (L + R) >> 1;
now = ++tcnt;
t[now].ch[0] = t[now].ch[1] = t[now].rev = 0;
t[now].fa = _f; t[now].siz = 1;
t[now].val = t[now].Min = a[mid]; t[now].id = t[now].sec = mid;
t[now].pos = now;
build(t[now].ch[0], L, mid - 1, now);
build(t[now].ch[1], mid + 1, R, now);
pushup(now);
}
In int find(int k)
{
int now = root;
while(2)
{
pushdown(now);
if(t[t[now].ch[0]].siz >= k) now = t[now].ch[0];
else if(t[t[now].ch[0]].siz + 1 == k) return now;
else k -= t[t[now].ch[0]].siz + 1, now = t[now].ch[1];
}
}
In int split(int L, int R)
{
int a = find(L), b = find(R + 2);
splay(a, 0); splay(b, a);
pushdown(root); pushdown(t[root].ch[1]);
return t[t[root].ch[1]].ch[0];
}
In void update(int L, int R)
{
int now = split(L, R); Rev(now);
}
In int query(int L, int R)
{
int now = split(L, R);
splay(t[now].pos, 0);
return t[t[root].ch[0]].siz;
}
In void _PrintTr(int now)
{
if(!now) return;
pushdown(now);
printf("nod:%d val:%d pos:%d Min:%d ls:%d rs:%d\n", now, t[now].val, t[now].pos, t[now].Min, t[now].ch[0], t[now].ch[1]);
_PrintTr(t[now].ch[0]); _PrintTr(t[now].ch[1]);
}
In void _PushDn(int now)
{
if(!now) return;
pushdown(now);
_PushDn(t[now].ch[0]); _PushDn(t[now].ch[1]);
}
int main()
{
n = read(); a[1] = a[n + 2] = INF;
for(int i = 2; i <= n + 1; ++i) a[i] = read();
build(root, 1, n + 2, 0);
for(int i = 1; i <= n; ++i)
{
int pos = query(i, n);
write(pos), space;
update(i, pos);
}
enter;
return 0;
}
[CQOI2014]排序机械臂的更多相关文章
- 【BZOJ3506】[CQOI2014] 排序机械臂(Splay)
点此看题面 大致题意: 给你\(n\)个数.第一次找到最小值所在位置\(P_1\),翻转\([1,P_1]\),第二次找到剩余数中最小值所在位置\(P_2\),翻转\([2,P_2]\),以此类推.求 ...
- P3165 [CQOI2014]排序机械臂
题目描述 为了把工厂中高低不等的物品按从低到高排好序,工程师发明了一种排序机械臂.它遵循一个简单的排序规则,第一次操作找到高度最低的物品的位置 P1P_1P1 ,并把左起第一个物品至 P1P_1P1 ...
- 洛谷P3165 [CQOI2014]排序机械臂
题目描述 为了把工厂中高低不等的物品按从低到高排好序,工程师发明了一种排序机械臂.它遵循一个简单的排序规则,第一次操作找到摄低的物品的位置P1,并把左起第一个至P1间的物品反序:第二次找到第二低的物品 ...
- Luogu P3165 [CQOI2014]排序机械臂
先讲一下和这题一起四倍经验的题: Luogu P4402 [Cerc2007]robotic sort 机械排序 SP2059 CERC07S - Robotic Sort UVA1402 Robot ...
- BZOJ1552[Cerc2007]robotic sort&BZOJ3506[Cqoi2014]排序机械臂——非旋转treap
题目描述 输入 输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000. 第二行为N个用空格隔开的正整数,表示N个物品最初排列的编号. 输出 输出共一行,N个用空格隔开 ...
- 【洛谷 P3165】 [CQOI2014]排序机械臂 (Splay)
题目链接 debug了\(N\)天没debug出来,原来是找后继的时候没有pushdown... 众所周知,,Splay中每个编号对应的节点的值是永远不会变的,因为所有旋转.翻转操作改变的都是父节点和 ...
- [UVA1402]Robotic Sort;[SP2059]CERC07S - Robotic Sort([洛谷P3165][CQOI2014]排序机械臂;[洛谷P4402][Cerc2007]robotic sort 机械排序)
题目大意:一串数字,使用如下方式排序: 先找到最小的数的位置$P_1$,将区间$[1,P_1]$反转,再找到第二小的数的位置$P_2$,将区间$[2,P_2]$反转,知道排序完成.输出每次操作的$P_ ...
- bzoj3506 [Cqoi2014]排序机械臂
bzoj3506 此题是一道比较简单的spaly题目. 用splay维护序列,将每个点排到对应的位置之后删除,这样比较容易区间翻转. 我的指针写法在洛谷上AC了,但在bzoj上RE. #include ...
- BZOJ3506/1502 [CQOI2014]排序机械臂
传送门 依然是一道splay的区间操作,需要注意的是要把下标离散化后来表示splay的节点,我不知道怎么搞所以索性弄了个$ValuetoNode$,看样子没什么问题, 感觉他那个传下标的方法太暴力了. ...
- [BZOJ3506] [Cqoi2014] 排序机械臂 (splay)
Description 同OJ1552 Input Output Sample Input Sample Output HINT Source Solution Q:哎不是同一道题吗为什么分两篇博客来 ...
随机推荐
- #15 time&datetime&calendar模块
前言 从这一节开始,记录一些常用的内置模块,模块的学习可能比较无聊,但基础就在这无聊的模块中,话不多说,本节记录和时间相关的模块! 一.time模块 Python中设计时间的模块有很多,但是最常用的就 ...
- 朴素贝叶斯分类器及Python实现
贝叶斯定理 贝叶斯定理是通过对观测值概率分布的主观判断(即先验概率)进行修正的定理,在概率论中具有重要地位. 先验概率分布(边缘概率)是指基于主观判断而非样本分布的概率分布,后验概率(条件概率)是根据 ...
- python学习笔记02--列表和元组
一.简介 数据结构是通过某种方式组织在一起的数据元素的集合. 序列是python中最基本的数据结构,python中包含6种内建的序列,分别是列表.元组.字符串.Unicode字符串.buffer对象和 ...
- 无法打开锁文件 /var/lib/dpkg/lock - open (13: 权限不够)
比如输入apt-get install eclipse,或者apt-get update 会提示 无法打开锁文件 /var/lib/dpkg/lock - open (13: 权限不够) 无法对状态 ...
- elasticsearch6.7 05. Document APIs(9)Bulk API
8.Bulk API 可以把多个index或delete操作放在单个bulk API中执行.这样可以极大地提高索引速度. /_bulkAPI使用如下的JSON结构: action_and_meta_d ...
- Java中,类与类,类中的代码执行顺序
代码的执行顺序如下: 1.一个类的静态代码块.构造代码块.构造方法的执行流程为: 静态代码块 > 构造代码块 > 构造方法 2.静态的内容是随着类的加载而加载,静态代码块的内容会优先执行 ...
- PHP7.27: connect mysql 5.7 using new mysqli_connect
<!doctype html> <html> <head> <meta name="viewport" content="wid ...
- 洛谷P3987 我永远喜欢珂朵莉~(set 树状数组)
题意 题目链接 Sol 不会卡常,自愧不如.下面的代码只有66分.我实在懒得手写平衡树了.. 思路比较直观:拿个set维护每个数出现的位置,再写个线段树维护区间和 #include<bits/s ...
- mysql 之库, 表的简易操作
一. 库的操作 1.创建数据库 创建数据库: create database 库名 charset utf8; charset uft8 可选项 1.2 数据库命名规范: 可以由字母.数字.下划 ...
- 从零开始学习html(一) Html介绍
我是初学者,这个是我学习的过程,当做笔记记录下来,如有错误希望高手指正. 原地址 一.代码初体验,制作我的第一个网页 <!DOCTYPE HTML> <html> <he ...