【HNOI2017】单旋
题面
题解
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】单旋的更多相关文章
- bzoj 4825: [Hnoi2017]单旋 [lct]
4825: [Hnoi2017]单旋 题意:有趣的spaly hnoi2017刚出来我就去做,当时这题作死用了ett,调了5节课没做出来然后发现好像直接用lct就行了然后弃掉了... md用lct不知 ...
- 【LG3721】[HNOI2017]单旋
[LG3721][HNOI2017]单旋 题面 洛谷 题解 20pts 直接模拟\(spaly\)的过程即可. 100pts 可以发现单旋最大.最小值到根,手玩是有显然规律的,发现只需要几次\(lin ...
- 4825: [Hnoi2017]单旋
4825: [Hnoi2017]单旋 链接 分析: 以后采取更保险的方式写代码!!!81行本来以为不特判也可以,然后就总是比答案大1,甚至出现负数,调啊调啊调啊调~~~ 只会旋转最大值和最小值,以最小 ...
- [BZOJ4825][HNOI2017]单旋(线段树+Splay)
4825: [Hnoi2017]单旋 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 667 Solved: 342[Submit][Status][ ...
- 【BZOJ4825】[Hnoi2017]单旋 线段树+set
[BZOJ4825][Hnoi2017]单旋 Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能 ...
- bzoj4825 [Hnoi2017]单旋
Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的必 ...
- BZOJ:4825: [Hnoi2017]单旋
Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的必 ...
- HNOI2017 单旋
题目描述 网址:https://www.luogu.org/problemnew/show/3721 大意: 有一颗单旋Splay(Spaly),以key值为优先度,总共有5个操作. [1] 插入一个 ...
- HNOI2017单旋
单旋 这道题做法贼多,LCT,splay,线段树什么的貌似都行. 像我这种渣渣只会线段树了(高级数据结构学了也不会用). 首先离线所有操作,因为不会有两个点值重复,所以直接离散. 一颗线段树来维护所有 ...
- P3721 [AH2017/HNOI2017]单旋
题目:https://www.luogu.org/problemnew/show/P3721 手玩一下即可AC此题. 结论:插入x后,x要么会成为x的前驱的右儿子,要么成为x的后继的左儿子,这取决于它 ...
随机推荐
- 初学Linux(一)关闭操作shutdown halt reboot
1.shutdown –h 10 #这个命令告诉大家,计算机将在10分钟后关机,并且会显示在登陆用户的当前屏幕中. 2.Shutdown –h now #立马关机 3.Shutdown –h 11:1 ...
- 如何查找论文是否被SCI,EI检索(转)
转自 http://blog.sina.com.cn/s/blog_564978430100iqpp.html 学术界,尤其是国内学术界,把SCI,EI看得太重,很多大学都要求博士毕业要有SC ...
- idea插件 总结 自认用比较不错的插件的总结
1.Background Image Plus 设置你喜欢的图片,提升你编码逼格!还可以设置以轮播图的形式变换图片 还可以设置图片的透明度等现实的方式 2.CodeGlance 类似SublimeTe ...
- 归并排序(php实现)
<?php function mergeSort(&$arr){ $len = count($arr); msort($arr,0,$len-1); } function msort(& ...
- python处理数据(一)
CSV数据处理 csv文件格式 逗号分隔符(csv),有时也称为字符分隔值,因为分隔字符也可以不是逗号,其文件以纯文本的形式存储表格数据(数字和文本).纯文本意味着该文件是一个字符序列,不含必须像二进 ...
- BZOJ4241:历史研究(回滚莫队)
Description IOI国历史研究的第一人——JOI教授,最近获得了一份被认为是古代IOI国的住民写下的日记.JOI教授为了通过这份日记来研究古代IOI国的生活,开始着手调查日记中记载的事件. ...
- 1054. [HAOI2008]移动玩具【BFS】
Description 在一个4*4的方框内摆放了若干个相同的玩具,某人想将这些玩具重新摆放成为他心中理想的状态,规定移动 时只能将玩具向上下左右四个方向移动,并且移动的位置不能有玩具,请你用最少的移 ...
- Day11 Java内部类
什么是内部类? 内部类是指在一个外部类的内部再定义一个类.内部类作为外部类的一个成员,并且依附于外部类而存在的.内部类可为静态,可用protected和private修饰(而外部类只能使用public ...
- selenium + python自动化测试unittest框架学习(六)分页
接触的项目分页的形式是以下形式: 想要获取总页数后,遍历执行翻页的功能,但由于分页是以javascript方法实现的,每次点击确定按钮后,页面就回刷新,webelement元素过期无法遍历下一个进行翻 ...
- c++中内存拷贝函数(C++ memcpy)详解
原型:void*memcpy(void*dest, const void*src,unsigned int count); 功能:由src所指内存区域复制count个字节到dest所指内存区域. 说明 ...