4825: [Hnoi2017]单旋
4825: [Hnoi2017]单旋
分析:
以后采取更保险的方式写代码!!!81行本来以为不特判也可以,然后就总是比答案大1,甚至出现负数,调啊调啊调啊调~~~
只会旋转最大值和最小值,以最小值为例,画一下图可以看出,旋转后,深度分成三部分讨论,最小值的深度(变为1),最小值右子树的深度(不变),其他的点的深度(整体加1)。所以线段树维护一下。
现在考虑如何插入一个点,可以知道一个点加入后一定是在前驱的右边,或者后继的左边。一个性质:前驱后继一定在splay上是一个是另一个的祖先的关系(反证:若中间存在一个点为它们两个的祖先,那么这个点前驱后继一定有一个是中间的点,没有重复的数字)。那么这个点加入的过程中,一定是加入在前驱后继中比较深的一个点。所以可以直接找到前驱后继,深度大的就是它的父节点。
找到根据splay的性质找到相应的区间,进行区间加减,单点求值。前驱后继可以直接在线段树上二分,或者直接用set。(或者直接splay)
代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<cctype>
#include<set>
#include<queue>
#include<vector>
#include<map>
#define Root 1, tot, 1
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#define Clear(x) ch[x][0] = ch[x][1] = fa[x] = 0
using namespace std;
typedef long long LL; inline int read() {
int x=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
} const int N = ; int T[N << ], tag[N << ], ch[N][], fa[N], a[N], disc[N], opt[N], Rt;
set<int> s;
set<int> :: iterator it; void pushdown(int rt) {
tag[rt << ] += tag[rt]; tag[rt << | ] += tag[rt];
T[rt << ] += tag[rt], T[rt << | ] += tag[rt];
tag[rt] = ;
}
void update(int l,int r,int rt,int L,int R,int v) {
if (L <= l && r <= R) {
tag[rt] += v; T[rt] += v; return;
}
if (tag[rt]) pushdown(rt);
int mid = (l + r) >> ;
if (L <= mid) update(lson, L, R, v);
if (R > mid) update(rson, L, R, v);
}
void Change(int l,int r,int rt,int p,int v) {
if (l == r) { T[rt] = v, tag[rt] = ; return ; }
if (tag[rt]) pushdown(rt);
int mid = (l + r) >> ;
if (p <= mid) Change(lson, p, v);
if (p > mid) Change(rson, p, v);
}
int query(int l,int r,int rt,int p) {
if (l == r) return T[rt];
if (tag[rt]) pushdown(rt);
int mid = (l + r) >> ;
if (p <= mid) return query(lson, p);
if (p > mid) return query(rson, p);
}
int main() {
int n = read(), tot = ;
for (int i = ; i <= n; ++i) {
opt[i] = read();
if (opt[i] == ) a[i] = read(), disc[++tot] = a[i];
}
s.insert(-1e9), s.insert(1e9);
sort(disc + ,disc + tot + );
for (int i = ; i <= n; ++i) if (opt[i] == ) a[i] = lower_bound(disc + , disc + tot + , a[i]) - disc; for (int pre, suc, now, mx, mn, i = ; i <= n; ++i) {
if (opt[i] == ) {
it = s.lower_bound(a[i]); suc = *it; pre = *(--it); now = ;
int d1 = -, d2 = -;
if (pre != -1e9) d1 = query(Root, pre);
if (suc != 1e9) d2 = query(Root, suc);
if (d1 > d2) now = d1 + , fa[a[i]] = pre, ch[pre][] = a[i];
if (d1 < d2) now = d2 + , fa[a[i]] = suc, ch[suc][] = a[i];
if (now == ) Rt = a[i], Clear(Rt);
Change(Root, a[i], now);
s.insert(a[i]);
}
else if (opt[i] & ) {
it = s.end(); it --; it --; mx = *it; now = query(Root, mx);
if (mx != Rt) { // 注意!!!此处需特判!!!!!!!!!!!!!
update(Root, , mx - , );
if (fa[mx] + <= mx - ) {
update(Root, fa[mx] + , mx - , -);
}
fa[ch[mx][]] = fa[mx]; ch[fa[mx]][] = ch[mx][];
ch[mx][] = Rt; fa[Rt] = mx; Rt = mx; fa[mx] = ;
Change(Root, mx, );
}
if (opt[i] == ) {
Rt = ch[mx][], fa[Rt] = ; Clear(mx);
s.erase(s.find(mx));
update(Root, , tot, -);
}
}
else {
it = s.begin(); it ++; mn = *it; now = query(Root, mn);
if (mn != Rt) {
update(Root, mn + , tot, );
if (mn + <= fa[mn] - ) {
update(Root, mn + , fa[mn] - , -);
}
fa[ch[mn][]] = fa[mn]; ch[fa[mn]][] = ch[mn][];
ch[mn][] = Rt; fa[Rt] = mn; Rt = mn; fa[mn] = ;
Change(Root, mn, );
}
if (opt[i] == ) {
Rt = ch[mn][]; fa[Rt] = ; Clear(mn);
s.erase(s.find(mn));
update(Root, , tot, -);
}
}
printf("%d\n",now);
}
return ;
}
4825: [Hnoi2017]单旋的更多相关文章
- bzoj 4825: [Hnoi2017]单旋 [lct]
4825: [Hnoi2017]单旋 题意:有趣的spaly hnoi2017刚出来我就去做,当时这题作死用了ett,调了5节课没做出来然后发现好像直接用lct就行了然后弃掉了... md用lct不知 ...
- BZOJ:4825: [Hnoi2017]单旋
Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的必 ...
- 【刷题】BZOJ 4825 [Hnoi2017]单旋
Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的必 ...
- bzoj 4825: [Hnoi2017]单旋【dfs序+线段树+hash】
这个代码已经不是写丑那么简单了--脑子浆糊感觉np++分分钟想暴起打死我--就这还一遍A过了-- 先都读进来hash一下,因为是平衡树所以dfs序直接按照点值来就好 对于每个操作: 1:set维护已插 ...
- [BZOJ4825][HNOI2017]单旋(线段树+Splay)
4825: [Hnoi2017]单旋 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 667 Solved: 342[Submit][Status][ ...
- 【LG3721】[HNOI2017]单旋
[LG3721][HNOI2017]单旋 题面 洛谷 题解 20pts 直接模拟\(spaly\)的过程即可. 100pts 可以发现单旋最大.最小值到根,手玩是有显然规律的,发现只需要几次\(lin ...
- 【BZOJ4825】[Hnoi2017]单旋 线段树+set
[BZOJ4825][Hnoi2017]单旋 Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能 ...
- bzoj P4825 [Hnoi2017]单旋——solution
Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据 结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的 ...
- bzoj4825 [Hnoi2017]单旋
Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的必 ...
随机推荐
- BZOJ 3224 Tyvj 1728 普通平衡树模板
题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=3224 题目大意: 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以 ...
- RedisClient的安装及基本使用
管理redis的可视化客户端目前较流行的有三个:Redis Client ; Redis Desktop Manager ; Redis Studio. 这里目前给大家介绍Redis Client 的 ...
- gluoncv 用已经训练好的模型参数,检测物体
当然这个模型参数,最好用自己的,否则不够精确,我自己的还没训练完. from matplotlib import pyplot as plt import gluoncv from gluoncv i ...
- [HEOI2012]朋友圈
题目 我们发现我们要求的是一个最大团问题,众所周知这是一个\(NP\)难问题,除了爆搜没有什么别的方法,但是这道题我们可以根据图的特殊性质入手 我们如果把\(B\)国的人分成奇数和偶数两类,就会发现奇 ...
- vim在插入模式粘贴代码缩进问题解决方法
转载自:https://blog.csdn.net/commshare/article/details/6215088 在vim粘贴代码会出现缩进问题,原因在于vim在代码粘贴时会自动缩进 解决方法: ...
- Odoo中的onchange
转载请注明原文地址:https://www.cnblogs.com/cnodoo/p/9280723.html [onchange=前端js函数,可以实现前端实时更新以及修改验证] onchange ...
- [19/04/16-星期二] 注解机制(Annotation,区别于comment(传统意义上的注释))
一.概念 作用: ——不是程序本身,可以对程序作出解释.(这一点和注释没什么区别) ——可以被其它程序(比如编译器)读取,这是区别于注释的最重要的一点. 格式: ——"@注释名" ...
- 【bbs】login.php
require的路径 整体结构的复用 渐变效果的加入 按钮:实现背景透明,文字不透明:在background-color中使用rgba,标准浏览器中,背景透明,文字不透明background-colo ...
- c++ 有swap函数
这是剑指offer数组中重复的数字那个题,直接使用的swap函数 class Solution { public: // Parameters: // numbers: an array of int ...
- Spring(五)之Bean定义继承和依赖注入
一.Bean定义继承 bean定义可以包含许多配置信息,包括构造函数参数,属性值和特定于容器的信息,例如初始化方法,静态工厂方法名称等. 子bean定义从父定义继承配置数据.子定义可以根据需要覆盖某些 ...