【LG3721】[HNOI2017]单旋
【LG3721】[HNOI2017]单旋
题面
题解
20pts
直接模拟\(spaly\)的过程即可。
100pts
可以发现单旋最大、最小值到根,手玩是有显然规律的,发现只需要几次\(link,cut\),那么我们维护原树的父子关系以及一颗\(LCT\)。
对于插入操作,由于插入的值肯定在前驱的右儿子或后继的左儿子,用\(set\)维护前驱后继即可。
建议自己独立找出规律,这里不再赘述,这题其实细节还是挺多的。
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <set>
#include <map>
using namespace std;
inline int gi() {
register int data = 0, w = 1;
register char ch = 0;
while (!isdigit(ch) && ch != '-') ch = getchar();
if (ch == '-') w = -1, ch = getchar();
while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar();
return w * data;
}
const int MAX_N = 2e5 + 5;
struct Node { int ch[2], fa, size; bool rev; } t[MAX_N];
struct Clone { int v, ls, rs, fa; } _t[MAX_N];
int root, tot;
bool get(int x) { return t[t[x].fa].ch[1] == x; }
bool nroot(int x) { return t[t[x].fa].ch[0] == x || t[t[x].fa].ch[1] == x; }
void pushup(int x) { t[x].size = t[t[x].ch[0]].size + t[t[x].ch[1]].size + 1; }
void putrev(int x) { swap(t[x].ch[0], t[x].ch[1]); t[x].rev ^= 1; }
void pushdown(int x) {
if (!t[x].rev) return ;
if (t[x].ch[0]) putrev(t[x].ch[0]);
if (t[x].ch[1]) putrev(t[x].ch[1]);
t[x].rev = 0;
}
void rotate(int x) {
int y = t[x].fa, z = t[y].fa, k = get(x);
if (nroot(y)) t[z].ch[get(y)] = x;
t[x].fa = z;
t[t[x].ch[k ^ 1]].fa = y, t[y].ch[k] = t[x].ch[k ^ 1];
t[y].fa = x, t[x].ch[k ^ 1] = y;
pushup(y), pushup(x);
}
void splay(int x) {
static int stk[MAX_N], top;
stk[top = 1] = x;
for (int i = x; nroot(i); i = t[i].fa) stk[++top] = t[i].fa;
for (int i = top; i; --i) pushdown(stk[i]);
while (nroot(x)) {
int y = t[x].fa;
if (nroot(y)) get(x) ^ get(y) ? rotate(x) : rotate(y);
rotate(x);
}
}
void access(int x) { for (int y = 0; x; y = x, x = t[x].fa) splay(x), t[x].ch[1] = y, pushup(x); }
void makeroot(int x) { access(x); splay(x); putrev(x); }
void link(int x, int y) { makeroot(x); t[x].fa = y; }
void split(int x, int y) { makeroot(x); access(y); splay(y); }
void cut(int x, int y) { split(x, y); t[x].fa = t[y].ch[0] = 0; pushup(y); }
set<int> st;
map<int, int> mp;
void insert(int v) {
int x = ++tot;
mp[v] = x, _t[x].v = v;
if (st.size() == 0) return st.insert(v), root = x, (void)puts("1");
set<int> :: iterator ite = st.upper_bound(v);
if (ite == st.end() || _t[mp[*ite]].ls) {
--ite;
int tmp = mp[*ite];
link(x, tmp), _t[tmp].rs = x, _t[x].fa = tmp;
} else {
int tmp = mp[*ite];
link(x, tmp), _t[tmp].ls = x, _t[x].fa = tmp;
}
st.insert(v);
return split(x, root), (void)printf("%d\n", t[root].size);
}
void splay_min() {
int x = mp[*st.begin()];
if (x == root) return (void)puts("1");
split(x, root); printf("%d\n", t[root].size);
cut(x, _t[x].fa); if (_t[x].rs) cut(x, _t[x].rs);
link(x, root); if (_t[x].rs) link(_t[x].fa, _t[x].rs);
_t[_t[x].fa].ls = _t[x].rs; if (_t[x].rs) _t[_t[x].rs].fa = _t[x].fa;
_t[x].fa = 0, _t[root].fa = x, _t[x].rs = root;
root = x;
}
void splay_max() {
int x = mp[*st.rbegin()];
if (x == root) return (void)puts("1");
split(x, root); printf("%d\n", t[root].size);
cut(x, _t[x].fa); if (_t[x].ls) cut(x, _t[x].ls);
link(x, root); if (_t[x].ls) link(_t[x].ls, _t[x].fa);
_t[_t[x].fa].rs = _t[x].ls; if (_t[x].ls) _t[_t[x].ls].fa = _t[x].fa;
_t[x].fa = 0, _t[root].fa = x, _t[x].ls = root;
root = x;
}
void del_min() {
int x = mp[*st.begin()];
if (root == x) {
puts("1");
if (_t[x].rs) cut(x, _t[x].rs);
_t[_t[x].rs].fa = 0, root = _t[x].rs;
st.erase(st.begin());
return ;
}
split(x, root); printf("%d\n", t[root].size);
cut(x, _t[x].fa); if (_t[x].rs) cut(x, _t[x].rs);
if (_t[x].rs) link(_t[x].fa, _t[x].rs);
_t[_t[x].fa].ls = _t[x].rs; if (_t[x].rs) _t[_t[x].rs].fa = _t[x].fa;
st.erase(st.begin());
}
void del_max() {
int x = mp[*st.rbegin()];
if (root == x) {
puts("1");
if (_t[x].ls) cut(x, _t[x].ls);
_t[_t[x].ls].fa = 0, root = _t[x].ls;
st.erase(--st.end());
return;
}
split(x, root); printf("%d\n", t[root].size);
cut(x, _t[x].fa); if (_t[x].ls) cut(x, _t[x].ls);
if (_t[x].ls) link(_t[x].ls, _t[x].fa);
_t[_t[x].fa].rs = _t[x].ls; if(_t[x].ls) _t[_t[x].ls].fa = _t[x].fa;
st.erase(--st.end());
}
int main () {
#ifndef ONLINE_JUDGE
freopen("cpp.in", "r", stdin);
#endif
int M = gi();
for (int i = 1; i <= M; i++) {
int op = gi();
switch (op) {
case 1: insert(gi()); break;
case 2: splay_min(); break;
case 3: splay_max(); break;
case 4: del_min(); break;
case 5: del_max(); break;
}
}
return 0;
}
【LG3721】[HNOI2017]单旋的更多相关文章
- bzoj 4825: [Hnoi2017]单旋 [lct]
4825: [Hnoi2017]单旋 题意:有趣的spaly hnoi2017刚出来我就去做,当时这题作死用了ett,调了5节课没做出来然后发现好像直接用lct就行了然后弃掉了... md用lct不知 ...
- 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的后继的左儿子,这取决于它 ...
随机推荐
- [翻译] NSDate-TimeAgo
NSDate-TimeAgo https://github.com/kevinlawler/NSDate-TimeAgo NSDate+TimeAgo has merged with DateTool ...
- 可以简易设置文字内边距的EdgeInsetsLabel
可以简易设置文字内边距的EdgeInsetsLabel 最终效果: 源码: EdgeInsetsLabel.h 与 EdgeInsetsLabel.m // // EdgeInsetsLabel.h ...
- Difference Between Arraylist And Vector : Core Java Interview Collection Question
Difference between Vector and Arraylist is the most common Core Java Interview question you will co ...
- 理解http请求
HTTP请求的GET方法可以用来抓取网页. HTTP(HyperText Transfer Protocol)是一套计算机通过网络进行通信的规则,计算机专家设计出HTTP,使HTTP客户(如Web浏览 ...
- 重置 Winsock:初始化计算机网络环境
初始化网络环境,以解决由于软件冲突.病毒原因造成的参数错误问题(复杂网络环境下慎用).批处理代码: netsh winhttp reset proxy netsh winhttp reset trac ...
- 详解权限管理(RBAC)的实现方法
在说权限管理前,应该先知道权限管理要有哪些功能: ().用户只能访问,指定的控制器,指定的方法 ().用户可以存在于多个用户组里 ().用户组可以选择,指定的控制器,指定的方法 ().可以添加控制器和 ...
- Zabbix日常监控(win_agent方式)
参考博文:https://www.cnblogs.com/xqzt/p/5130469.html https://www.cnblogs.com/zoulongbin/p/6395047.html 本 ...
- zabbix日常监控项TCP连接状态(六)
TCP的连接状态对于我们web服务器来说是至关重要的,尤其是并发量ESTAB或者是syn_recv值,假如这个值比较大的话我们可以认为是不是受到了攻击,或是time_wait值比较高的话,我们要考虑看 ...
- kudu安装部署
安装部署节点规划 节点 kudu-master kudu-tserver node01 是 是 node02 是 是 node03 是 是 配置本地Yum的Repository 下载kudu安装yum ...
- 【原创】uwsgi中多进程+多线程原因以及串行化accept() - thunder_lock说明
如有不对,请详细指正. 最近再研究uwsgi如何部署python app,看uwsgi的文档,里面有太多的参数,但每个参数的解释太苍白,作为菜鸟的我实在是不懂.想搞清楚uwsgi的工作原因以及里面的一 ...