题面

题解

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. Intel Nehalem微架构Calpella平台机型Windows XP系统下如何开启AHCI硬盘工作模式(XP系统下如何加载AHCI驱动)

    问题描述用户来电表示使用IDE模式安装XP系统后开启AHCI模式会出现开机蓝屏重启的问题,咨询如何在XP下加载AHCI驱动,以便开启BIOS中AHCI选项来发挥硬盘的最佳性能   问题分析 Windo ...

  2. Oracle GI 日志收集工具 - TFA

    1.TFA的目的: TFA是个11.2版本上推出的用来收集Grid Infrastructure/RAC环境下的诊断日志的工具,它可以用非常简单的命令协助用户收集RAC里的日志,以便进一步进行诊断:T ...

  3. [翻译] About Core Image

    About Core Image Core Image is an image processing and analysis technology designed to provide near ...

  4. Linux 系统的DNS配置文件

    系统的DNS配置文件 方式一: 界面操作 setup -->界面配置网络,网关等 方式二: 修改配置文件 # 修改配置 ==>vi /etc/resolv.conf -->man r ...

  5. CSS学习摘要-定位实例

    CSS学习摘要-定位实例 注:全文摘自MDN-CSS定位实例 列表消息盒子 我们研究的第一个例子是一个经典的选项卡消息框,你想用一块小区域包括大量信息时,一个非常常用的特征.这包括含有大信息量的应用, ...

  6. Git忽略提交 .gitignore配置。自动生成IDE的.gitignore。解决gitignore不生效

    语法 以”#”号开头表示注释: 以斜杠“/”开头表示目录: 以星号“*”通配多个字符: 以问号“?”通配单个字符 以方括号“[]”包含单个字符的匹配列表: 以叹号“!”表示不忽略(跟踪)匹配到的文件或 ...

  7. amcharts属性

    Amcharts的特点包含: *动画或静态 *价值轴能够扭转 *线性或对数轴的价值尺度 *提前定义或定制的子弹 *定制描写叙述不论什么数据点 *点击栏目/酒吧(可用于钻孔下来图表) *梯度弥漫 *价值 ...

  8. BZOJ4891:[TJOI2017]龙舟(Pollard-Rho,exgcd)

    Description 加里敦大学有一个龙舟队,龙舟队有n支队伍,每只队伍有m个划手,龙舟比赛是一个集体项目,和每个人的能力息息相关,但由于龙舟讲究配合,所以评价队伍的能力的是一个值c = (b1*b ...

  9. Zookeeper入门(一)之概述

    今天主要讲这么几个方面? 1.分布式应用: 2.什么是Zookeeper: 3.使用Zookkeeper有什么好处: ZooKeeper是一种分布式协调服务,用于管理大型主机.在分布式环境中协调和管理 ...

  10. Vue2.5开发去哪儿网App 从零基础入门到实战项目

    第1章 课程介绍本章主要介绍课程的知识大纲,学习前提,讲授方式及预期收获. 1-1 课程简介 试看第2章 Vue 起步本章将快速讲解部分 Vue 基础语法,通过 TodoList 功能的编写,在熟悉基 ...