题面

题解

trajan的spaly是O(1)的(逃

通过看题解手玩发现只要将最值的点放到树根,其他的父子关系不需要变。

于是想到动态连边和断边的数据结构:\(\mathrm{LCT}\),于是用\(\mathrm{LCT}\)维护\(\mathrm{splay}\)。

这样后面的四个操作就解决了。

第一个操作中,第一个点要么接在前驱的右儿子,要么接在后继的左儿子。

于是再开个set求一下前驱后继即可。

代码

很多可以复制粘贴,所以也不算很长。

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<set>
#include<map>
#define RG register
#define file(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define clear(x, y) memset(x, y, sizeof(x)) inline int read()
{
int data = 0, w = 1; char ch = getchar();
while(ch != '-' && (!isdigit(ch))) ch = getchar();
if(ch == '-') w = -1, ch = getchar();
while(isdigit(ch)) data = data * 10 + (ch ^ 48), ch = getchar();
return data * w;
} const int maxn(200010);
int m, root, fa[maxn], son[2][maxn], stk[maxn], top;
int size[maxn], rev[maxn], cur, val[maxn], lson[maxn], rson[maxn], Fa[maxn];
inline bool isroot(int x) { return son[0][fa[x]] != x && son[1][fa[x]] != x; }
inline int getSon(int x) { return son[1][fa[x]] == x; }
inline void update(int x) { size[x] = size[son[0][x]] + size[son[1][x]] + 1; }
inline void pushdown(int x)
{
if(!rev[x]) return;
rev[son[0][x]] ^= 1;
rev[son[1][x]] ^= 1;
rev[x] = 0, std::swap(son[0][x], son[1][x]);
} inline void rotate(int x)
{
int f = fa[x], g = fa[f], l = getSon(x), r = l ^ 1;
if(!isroot(f)) son[getSon(f)][g] = x;
fa[x] = g, fa[f] = x, fa[son[r][x]] = f;
son[l][f] = son[r][x], son[r][x] = f;
update(f), update(x);
} void splay(int x)
{
stk[top = 1] = x;
for(int i = x; !isroot(i); i = fa[i]) stk[++top] = fa[i];
while(top) pushdown(stk[top--]);
for(; !isroot(x); rotate(x)) if(!isroot(fa[x]))
rotate(getSon(fa[x]) ^ getSon(x) ? x : fa[x]);
} void access(int x)
{
for(int t = 0; x; t = x, x = fa[x])
splay(x), son[1][x] = t, update(x);
} inline void makeroot(int x) { access(x); splay(x); rev[x] ^= 1; }
inline void split(int x, int y) { makeroot(x); access(y); splay(y); }
inline int getdep(int x) { split(x, root); return size[root]; }
inline void link(int x, int y) { makeroot(x); fa[x] = y; }
inline void cut(int x, int y)
{
split(x, y); if(son[0][y] == x) son[0][y] = 0;
fa[x] = 0;
} std::map<int, int> map;
std::set<int> set; void insert(int x)
{
int now = map[x] = ++cur;
if(set.empty()) return (void) (set.insert(x), root = now, puts("1"));
std::set<int>::iterator it = set.upper_bound(x);
if(it == set.end() || lson[map[*it]])
{
--it; int node = map[*it]; link(now, node);
Fa[now] = node, rson[node] = now;
}
else
{
int node = map[*it]; link(now, node);
Fa[now] = node, lson[node] = now;
}
set.insert(x); printf("%d\n", getdep(now));
} void splay_min()
{
int x = map[*set.begin()];
if(root == x) return (void) (puts("1"));
printf("%d\n", getdep(x)); cut(x, Fa[x]);
if(rson[x]) cut(x, rson[x]);
link(x, root); if(rson[x]) link(Fa[x], rson[x]);
lson[Fa[x]] = rson[x]; if(rson[x]) Fa[rson[x]] = Fa[x];
Fa[x] = 0, Fa[root] = x, rson[x] = root; root = x;
} void splay_max()
{
int x = map[*set.rbegin()];
if(root == x) return (void) (puts("1"));
printf("%d\n", getdep(x)); cut(x, Fa[x]);
if(lson[x]) cut(x, lson[x]);
link(x, root); if(lson[x]) link(lson[x], Fa[x]);
rson[Fa[x]] = lson[x]; if(lson[x]) Fa[lson[x]] = Fa[x];
Fa[x] = 0, Fa[root] = x, lson[x] = root; root = x;
} void del_min()
{
int x = map[*set.begin()];
if(root == x)
{
puts("1"); if(rson[x]) cut(x, rson[x]);
Fa[rson[x]] = 0; root = rson[x];
set.erase(set.begin()); return;
}
printf("%d\n", getdep(x)); cut(x, Fa[x]);
if(rson[x]) cut(x, rson[x]), link(Fa[x], rson[x]);
lson[Fa[x]] = rson[x]; if(rson[x]) Fa[rson[x]] = Fa[x];
set.erase(set.begin());
} void del_max()
{
int x = map[*set.rbegin()];
if(root == x)
{
puts("1"); if(lson[x]) cut(x, lson[x]);
Fa[lson[x]] = 0; root = lson[x];
set.erase(--set.end()); return;
}
printf("%d\n", getdep(x)); cut(x, Fa[x]);
if(lson[x]) cut(x, lson[x]), link(lson[x], Fa[x]);
rson[Fa[x]] = lson[x]; if(lson[x]) Fa[lson[x]] = Fa[x];
set.erase(--set.end());
} int main()
{
m = read();
for(RG int i = 1; i <= m; i++)
{
int opt = read();
switch(opt)
{
case 1: insert(read()); break;
case 2: splay_min(); break;
case 3: splay_max(); break;
case 4: del_min(); break;
case 5: del_max(); break;
}
}
return 0;
}

【HNOI2017】单旋的更多相关文章

  1. bzoj 4825: [Hnoi2017]单旋 [lct]

    4825: [Hnoi2017]单旋 题意:有趣的spaly hnoi2017刚出来我就去做,当时这题作死用了ett,调了5节课没做出来然后发现好像直接用lct就行了然后弃掉了... md用lct不知 ...

  2. 【LG3721】[HNOI2017]单旋

    [LG3721][HNOI2017]单旋 题面 洛谷 题解 20pts 直接模拟\(spaly\)的过程即可. 100pts 可以发现单旋最大.最小值到根,手玩是有显然规律的,发现只需要几次\(lin ...

  3. 4825: [Hnoi2017]单旋

    4825: [Hnoi2017]单旋 链接 分析: 以后采取更保险的方式写代码!!!81行本来以为不特判也可以,然后就总是比答案大1,甚至出现负数,调啊调啊调啊调~~~ 只会旋转最大值和最小值,以最小 ...

  4. [BZOJ4825][HNOI2017]单旋(线段树+Splay)

    4825: [Hnoi2017]单旋 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 667  Solved: 342[Submit][Status][ ...

  5. 【BZOJ4825】[Hnoi2017]单旋 线段树+set

    [BZOJ4825][Hnoi2017]单旋 Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能 ...

  6. bzoj4825 [Hnoi2017]单旋

    Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的必 ...

  7. BZOJ:4825: [Hnoi2017]单旋

    Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的必 ...

  8. HNOI2017 单旋

    题目描述 网址:https://www.luogu.org/problemnew/show/3721 大意: 有一颗单旋Splay(Spaly),以key值为优先度,总共有5个操作. [1] 插入一个 ...

  9. HNOI2017单旋

    单旋 这道题做法贼多,LCT,splay,线段树什么的貌似都行. 像我这种渣渣只会线段树了(高级数据结构学了也不会用). 首先离线所有操作,因为不会有两个点值重复,所以直接离散. 一颗线段树来维护所有 ...

  10. P3721 [AH2017/HNOI2017]单旋

    题目:https://www.luogu.org/problemnew/show/P3721 手玩一下即可AC此题. 结论:插入x后,x要么会成为x的前驱的右儿子,要么成为x的后继的左儿子,这取决于它 ...

随机推荐

  1. 《SQL Server 2008从入门到精通》--20180710

    目录 1.使用Transact-SQL语言编程 1.1.数据定义语言DDL 1.2.数据操纵语言DML 1.3.数据控制语言DCL 1.4.Transact-SQL语言基础 2.运算符 2.1.算数运 ...

  2. 用Spider引擎解决数据库垂直和水平拆分的问题

    作者介绍 张秀云,网名飞鸿无痕,现任职于腾讯,负责腾讯金融数据库的运维和优化工作.2007年开始从事运维方面的工作,经历过网络管理员.Linux运维工程师.DBA.分布式存储运维等多个IT职位.对Li ...

  3. 名词解释:Linux内存管理之RSS和VSZ

    Linux内存管理中不管是top命令还是pmap命令,都会有RSS和VSZ这两个名词,这里解释一下: RSS( Resident Set Size )常驻内存集合大小,表示相应进程在RAM中占用了多少 ...

  4. windows多线程同步

    概述 任何单个应用程序都不能完全使该处理器达到满负荷.当一个线程遇到较长等待时间事件时,同步多线程还允许另一线程中的指令使用所有执行单元.例如,当一个线程发生高速缓存不命中,另一个线程可以继续执行.同 ...

  5. 转:Window_Open详解

       引:Window_Open详解一.window.open()支持环境:JavaScript1.0+/JScript1.0+/Nav2+/IE3+/Opera3+ 二.基本语法:window.op ...

  6. 通过runtime获取对象相关信息

    通过runtime获取对象相关信息 在这里,本人给大家提供一个runtime关于NSObject的扩展,用来显示各种NSObject中的信息,这有助于你来分析类的组成:) 先准备以下类供测试: Mod ...

  7. 一、TCL事务控制语言 二、MySQL中的约束 三、多表查询(重点) 四、用户的创建和授权 五、MySQL中的索引

    一.TCL事务控制语言###<1>事务的概念 事务是访问并可能更新数据库中各种数据项的执行单元. 事务是一条SQL语句,一组SQL语句,或者整个程序. 事务是恢复和并发控制的基本单位. 事 ...

  8. Docker实战(十)之分布式处理与大数据平台

    分布式系统和大数据处理平台是目前业界关注的热门技术. 1.RabbitMQ RabbitMQ是一个支持AMQP的开源消息队列实现,由Erlang编写,因以高性能.高可用以及可伸缩性出名.它支持多种客户 ...

  9. composer设置国内镜像

    使用composer时,输入命令执行后半天没有反应,并最后是失败的消息. 如下载项目中的框架文件时: composer install 一直没有反应 [注]添加参数-vvv可尽可能多的输出执行信息,帮 ...

  10. jenkins slave 挂载

    http://blog.sina.com.cn/s/blog_13cc013b50102wiau.html