[HNOI 2017]单旋
Description

Input
Output
Sample Input
1 2
1 1
1 3
4
5
Sample Output
1
2
2
2
2
题解
参考了PIPIBoss的做法。
我们手玩一下单旋,发现其如果只改变最大最小值时,主要的性质就是整棵$splay$的形态不会发生很大的改变。
例如旋最小值到根,其实就相当于将最小值的节点取出来,最小值的右儿子连向最小值的父亲。接着再把最小值对应的节点接在原来的根的父亲上。
最大值同理。那么就可以用$LCT$维护了。
对于插入操作,很显然的是这个新插入的节点肯定接向其前驱的右儿子或后继的左儿子。另外,这两个儿子肯定有一个是空的,有一个不空。另外,不空的儿子就是前驱和后继两个中深度较深节点的儿子。
我们将权值离散,找前驱后继就交给$STL-set$,另外还要额外开数组来记录原来$splay$树的形态。
//It is made by Awson on 2017.12.27
#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define LD long double
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
using namespace std;
const int N = 1e5;
const int INF = ~0u>>; int m, a[N+], top;
struct Opt {
int opt, x;
}q[N+];
struct Link_Cut_Tree {
int ch[N+][], pre[N+], size[N+], isrt[N+], rev[N+];
set<int>S;
int f[N+], c[N+][], root;
Link_Cut_Tree () {
for (int i = ; i <= N; i++) size[i] = isrt[i] = ;
S.insert(-INF), S.insert(INF);
}
void pushdown(int o) {
if (!o || !rev[o]) return;
int ls = ch[o][], rs = ch[o][];
swap(ch[ls][], ch[ls][]), swap(ch[rs][], ch[rs][]);
rev[ls] ^= , rev[rs] ^= , rev[o] = ;
}
void push(int o) {
if (!isrt[o]) push(pre[o]);
pushdown(o);
}
void pushup(int o) {
if (!o) return;
size[o] = size[ch[o][]]+size[ch[o][]]+;
}
void rotate(int o, int kind) {
int p = pre[o];
ch[p][!kind] = ch[o][kind], pre[ch[o][kind]] = p;
if (isrt[p]) isrt[o] = , isrt[p] = ;
else ch[pre[p]][ch[pre[p]][] == p] = o;
pre[o] = pre[p];
ch[o][kind] = p, pre[p] = o;
pushup(p), pushup(o);
}
void splay(int o) {
push(o);
while (!isrt[o]) {
if (isrt[pre[o]]) rotate(o, ch[pre[o]][] == o);
else {
int p = pre[o], kind = ch[pre[p]][] == p;
if (ch[p][kind] == o) rotate(o, !kind), rotate(o, kind);
else rotate(p, kind), rotate(o, kind);
}
}
}
void access(int o) {
int y = ;
while (o) {
splay(o); size[o] -= size[ch[o][]];
isrt[ch[o][]] = , isrt[ch[o][] = y] = ;
o = pre[y = o];
pushup(o);
}
}
void makeroot(int o) {
access(o), splay(o);
rev[o] ^= , swap(ch[o][], ch[o][]);
}
void link(int x, int y) {
if (!x || !y) return;
makeroot(x); pre[x] = y;
}
void cut(int x, int y) {
if (!x || !y) return;
makeroot(x), access(y), splay(y);
size[y] -= size[x];
ch[y][] = pre[x] = , isrt[x] = ;
}
int query(int x, int y) {
makeroot(x), access(y), splay(y);
return size[ch[y][]]+;
}
int insert(int x) {
if (!root) {
root = x; S.insert(x); return ;
}
int pre = *(--S.lower_bound(x)), nex = *(S.upper_bound(x)), o;
if (pre == -INF) o = nex;
else if (nex == INF) o = pre;
else {
int depx = query(root, pre), depy = query(root, nex);
if (depx > depy) o = pre;
else o = nex;
}
f[x] = o, c[o][x > o] = x; link(o, x); S.insert(x);
return query(root, x);
}
int find_min() {
int o = *(++S.begin()), fa = f[o], child = c[o][];
int ans = query(root, o);
if (o != root) {
cut(o, fa), cut(child, o), link(child, fa), link(root, o);
c[o][] = root, f[root] = o; root = o; f[o] = ; c[fa][] = child, f[child] = fa;
}
return ans;
}
int find_max() {
int o = *(--(--S.end())), fa = f[o], child = c[o][];
int ans = query(root, o);
if (o != root) {
cut(o, fa), cut(child, o), link(child, fa), link(root, o);
c[o][] = root, f[root] = o; root = o; f[o] = ; c[fa][] = child, f[child] = fa;
}
return ans;
}
int del_min() {
int o = *(++S.begin()), fa = f[o], child = c[o][];
int ans = query(root, o);
cut(o, fa), cut(o, child); link(fa, child);
f[child] = fa, c[fa][] = child;
S.erase(S.find(o)); f[o] = c[o][] = c[o][] = ;
if (root == o) root = child, f[child] = ;
return ans;
}
int del_max() {
int o = *(--(--S.end())), fa = f[o], child = c[o][];
int ans = query(root, o);
cut(o, fa), cut(o, child); link(fa, child);
f[child] = fa, c[fa][] = child;
S.erase(S.find(o)); f[o] = c[o][] = c[o][] = ;
if (root == o) root = child, f[child] = ;
return ans;
}
}T; void work() {
scanf("%d", &m);
for (int i = ; i <= m; i++) {
scanf("%d", &q[i].opt);
if (q[i].opt == ) {
scanf("%d", &q[i].x); a[++top] = q[i].x;
}
}
sort(a+, a++top); top = unique(a+, a+top+)-a-;
for (int i = ; i <= m; i++) {
if (q[i].opt == ) printf("%d\n", T.insert(lower_bound(a+, a+top+, q[i].x)-a));
else if (q[i].opt == ) printf("%d\n", T.find_min());
else if (q[i].opt == ) printf("%d\n", T.find_max());
else if (q[i].opt == ) printf("%d\n", T.del_min());
else printf("%d\n", T.del_max());
}
}
int main() {
work();
return ;
}
[HNOI 2017]单旋的更多相关文章
- bzoj4825 [Hnoi2017]单旋
Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的必 ...
- BZOJ:4825: [Hnoi2017]单旋
Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的必 ...
- bzoj 4825: [Hnoi2017]单旋 [lct]
4825: [Hnoi2017]单旋 题意:有趣的spaly hnoi2017刚出来我就去做,当时这题作死用了ett,调了5节课没做出来然后发现好像直接用lct就行了然后弃掉了... md用lct不知 ...
- 【BZOJ4825】【HNOI2017】单旋(Link-Cut Tree)
[BZOJ4825][HNOI2017]单旋(Link-Cut Tree) 题面 题面太长,懒得粘过来 题解 既然题目让你写Spaly 那就肯定不是正解 这道题目,让你求的是最大/最小值的深度 如果有 ...
- HNOI2017 单旋
题目描述 网址:https://www.luogu.org/problemnew/show/3721 大意: 有一颗单旋Splay(Spaly),以key值为优先度,总共有5个操作. [1] 插入一个 ...
- 「AHOI / HNOI2017」单旋
「AHOI / HNOI2017」单旋 题目链接 H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能多,效率高,掌握这种 ...
- HNOI2017单旋
单旋 这道题做法贼多,LCT,splay,线段树什么的貌似都行. 像我这种渣渣只会线段树了(高级数据结构学了也不会用). 首先离线所有操作,因为不会有两个点值重复,所以直接离散. 一颗线段树来维护所有 ...
- P3721 [AH2017/HNOI2017]单旋
题目:https://www.luogu.org/problemnew/show/P3721 手玩一下即可AC此题. 结论:插入x后,x要么会成为x的前驱的右儿子,要么成为x的后继的左儿子,这取决于它 ...
- 洛谷P3721 单旋
什么毒瘤...... 题意:模拟一棵单旋splay,求每次插入,splay最值,删除最值的操作次数. 解:乍一看感觉很神,又因为是LCT题单上的,然后就折磨了我好久,最后跑去看题解... 居然是手玩找 ...
随机推荐
- java web 初学
我希望在本学期本堂课上学会使用java web 框架 精通mvc架构模式 学会通过框架和数据库对产品进行构造与编写. 我计划每周用16小时的时间进行学习java web 一周4学时上课时间 周一到周五 ...
- 敏捷冲刺每日报告--day2
1 团队介绍 团队组成: PM:齐爽爽(258) 小组成员:马帅(248),何健(267),蔡凯峰(285) Git链接:https://github.com/WHUSE2017/C-team ...
- 20145237《Java程序设计》实验报告一
实验一 Java开发环境的熟悉(Windows + Eclipse) 实验内容 1.使用JDK编译.运行简单的Java程序: 2.使用Eclipse 编辑.编译.运行.调试Java程序. 实验要求 1 ...
- java连接jdbc Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by defa
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jsp_db","root",& ...
- java的socket通信
本文讲解如何用java实现网络通信,是一个非常简单的例子,我比较喜欢能够立马看到结果,所以先上代码再讲解具体细节. 服务端: import java.io.BufferedReader; import ...
- ebtables和iptables与linux bridge的交互
本文为翻译文,不一定是逐字逐句的翻译,而且中间会加上自己的一点见解,如有理解错误的地方,还请大家指出,我定虚心学习.原文见链接 其中斜体字是自己的理解,建议和ebtables手册和iptables手册 ...
- centos7 安装docker
1.首先cent7 基本是在vm上完全安装'. 2.参考官方网站安装 1.https://wiki.centos.org/AdditionalResources/Repositories OS req ...
- Oracle闪回技术
(一)闪回技术概要 闪回技术是数据库备份与恢复的重要补充手段,主要包括以下7种特性: 特性 原理 数据库支持 闪回查询(Flashback Query) 利用undo表空间中的回退信息,查询过去某个时 ...
- 原生JS封装时间运动函数
/*讲时间运动之前先给大家复习一下运动函数 通常大家都会写运动框架,一个定时器(Timer),一个步长(step 就是每次运动的距离),一个当前位置(current)一个目标位置(target),然后 ...
- 通过java把excel内容上传到mysql
mysql 表列名 num1,num2,num3,num4,num5,num6 表名Excle 上传的方法 package com.web.connection; import java.io.Fi ...