【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的后继的左儿子,这取决于它 ...
随机推荐
- [WINCE|VS2008] 用在PC上调试WINCE程序
http://www.danielmoth.com/Blog/deploy-to-my-computer.aspx 作者:The Moth 步骤: 1. 在VS2008中打到 Device Optio ...
- [IIS | 用户权限] Connect as... 的设置
ApplicationPoolIdentity is actually the best practice to use in IIS7. It is a dynamically created, u ...
- where条件使用to_char条件太慢
where条件使用to_char 会不使用索引并使用nestedloop 可以用with as解决 最后再加上to_char的条件语句
- SQL Server 常用数据类型
char: 固定长度,存储ANSI字符,不足的补英文半角空格. varchar: 可变长度,存储ANSI字符,根据数据长度自动变化. nchar: 固定长度存储Unicode字符,汉字英文 ...
- terminal 总结
(1) Mac添加命令别名 切换到用户主目录 (2). 编辑或新建.bash_profile文件 (3). 添加别名 alias ll='ls -Alh' (4). 重载该配置文件 source .b ...
- vim高级操作命令
1.首先在命令模式下,输入“:set nu”显示行号:通过行号确定你要删除的行:命令输入“:32,65d”,回车键,32-65行就被删除了,很快捷吧如果无意中删除错了,可以使用‘u’键恢复(命令模式下 ...
- python第八课——random模块的使用
2.2.如何获取随机整数值? 引入random模块的使用 randint(a,b)函数:作用:返回给程序一个[a,b]范围内的随机整数注意:含头含尾闭区间 思路步骤: 第一步:导入random模块到相 ...
- java 扁平化输出json所有节点key/value
本章主要介绍用java实现扁平化输出json所有节点key/value(包含所有内层子节点) 1.json结构 目的输出bill_list下的datalist里的子节点key/value 2.实现代码 ...
- Python学习之路 (四)爬虫(三)HTTP和HTTPS
HTTP和HTTPS HTTP协议(HyperText Transfer Protocol,超文本传输协议):是一种发布和接收 HTML页面的方法. HTTPS(Hypertext Transfer ...
- virtualbox+vagrant学习-2(command cli)-21-vagrant up命令
Up 格式: vagrant up [options] [name|id] 这个命令根据你的Vagrantfile文件创建和配置客户机. 这是“vagrant”中最重要的一个命令,因为它是创建任何va ...