题面

题解

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. ASP.NET MVC 5搭建自己的视图基架 (CodeTemplate)

    我们知道,在MVC项目中添加视图时,在添加面板有模板可以选择,这里会有人疑问,这个模板位于哪里?我可以搭建自己的基架吗? 首先回答第二个问题,答案是当然可以 我这里使用的是Visual Studio ...

  2. swift版的CircleView

    swift版的CircleView 效果图 源码 // // CircleView.swift // CircleView // // Created by YouXianMing on 15/10/ ...

  3. 封装NSMapTable并简易的使用

    封装NSMapTable并简易的使用 NSMapTable是弱引用的字典,可以用来存储对象,该对象消失了也没有关系,对于控制器越级跳转相当有用:) WeakDictionary.h 与 WeakDic ...

  4. 团队作业4(Alpha版本)

    项目名称:音乐播放器 项目成员: 张慧敏(201421122032) 苏晓薇(201421031033) 欧阳时康(201421122050) 会议记录:  主要讨论任务的分配和实现过程中已实现和未实 ...

  5. 前端技术-HTML页面的加载

    HTML页面的加载 HTML页面的加载实际上是基于http过程+浏览器对数据的解析渲染. http协议的请求过程是基于TCP协议的.http是要基于TCP连接基础上,简单的说,TCP单纯建立连接,不涉 ...

  6. Installing Oracle Database 12c Release 2(12.2) RAC on RHEL7.3 in Silent Mode

    概要 在RHEL7静默方式安装oracle database 12.2 RAC. 一.环境配置 1. 配置hosts文件 cp /etc/hosts /etc/hosts_$(date +%Y%d%m ...

  7. Python全栈开发:list 、tuple以及dict的总结

    总结: 列表:增:append(),inset(),extend() 删:pop(),remove(),clear(),del 改:a.通过指定元素和切片重新赋值.b.可以使用repelace替换列表 ...

  8. Android Studio3.0 配置AndroidAnnotation注解框架

    前言android学习了一段时间后,想要开发一款App,但是一些复杂的代码写多了实在麻烦,就到网上找了找简便的方法,于是在众多的注解开发框架中,找到了Android Annotation这个框架,这里 ...

  9. [USACO08NOV]Cheering up the Cow

    嘟嘟嘟 这道题删完边后是一棵树,那么一定和最小生成树有关啦. 考虑最后的生成树,无论从哪一个点出发,每一条边都会访问两次,而且在看一看样例,会发现走第w条边(u, v)的代价是L[w] * 2 + c ...

  10. head头的设计:rfcn light-head rfcn

    faster缺点:1.不是全卷积,roi出来后是两个fc层,这样会丧失平移变性.   2.每个roi都要单独经过两个fc层,也就是分别进行分类和回归,耗时 也有种说法是roi-pooling后导致平移 ...