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]单旋的更多相关文章

  1. bzoj 4825: [Hnoi2017]单旋 [lct]

    4825: [Hnoi2017]单旋 题意:有趣的spaly hnoi2017刚出来我就去做,当时这题作死用了ett,调了5节课没做出来然后发现好像直接用lct就行了然后弃掉了... md用lct不知 ...

  2. BZOJ:4825: [Hnoi2017]单旋

    Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的必 ...

  3. 【刷题】BZOJ 4825 [Hnoi2017]单旋

    Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的必 ...

  4. bzoj 4825: [Hnoi2017]单旋【dfs序+线段树+hash】

    这个代码已经不是写丑那么简单了--脑子浆糊感觉np++分分钟想暴起打死我--就这还一遍A过了-- 先都读进来hash一下,因为是平衡树所以dfs序直接按照点值来就好 对于每个操作: 1:set维护已插 ...

  5. [BZOJ4825][HNOI2017]单旋(线段树+Splay)

    4825: [Hnoi2017]单旋 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 667  Solved: 342[Submit][Status][ ...

  6. 【LG3721】[HNOI2017]单旋

    [LG3721][HNOI2017]单旋 题面 洛谷 题解 20pts 直接模拟\(spaly\)的过程即可. 100pts 可以发现单旋最大.最小值到根,手玩是有显然规律的,发现只需要几次\(lin ...

  7. 【BZOJ4825】[Hnoi2017]单旋 线段树+set

    [BZOJ4825][Hnoi2017]单旋 Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能 ...

  8. bzoj P4825 [Hnoi2017]单旋——solution

    Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据 结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的 ...

  9. bzoj4825 [Hnoi2017]单旋

    Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的必 ...

随机推荐

  1. maven的pom.xml文件报错问题

    第一次用 Spring Starter Project 创建一个Spring应用时,POM 文件报错: Project build error: Non-resolvable parent POM f ...

  2. 【[SHOI2007]园丁的烦恼】

    \(CDQ\) 分治的神奇操作 这个问题跟偏序问题好像差的不小啊 但是就是可以转化过去 对于一个查询我们可以把它拆成四个,也就是用二维前缀和的方式来查询 我们发现其实前缀和的定义就是多少个点的横纵坐标 ...

  3. F2eTest和uirecorder自动化测试环境部署填坑记录

    坑1:尝试部署的时候只在opennode.bat里面填写了两个浏览器,测试通过后再增加其他浏览器,页面上一直不显示. 填坑:需要清空数据库里的`wd_browsers`和`wd_nodes`表,然后重 ...

  4. mvc项目中Controller执行完毕重定向到html的一个页面中

    String ip = request.getLocalAddr(); //取得服务器IP int port = request.getLocalPort(); //取得服务器端口 String ur ...

  5. Shell笔记-02

    Shell支持自定义变量. 定义变量 定义变量时,变量名不加美元符号($),如: variableName="value" 注意,变量名和等号之间不能有空格,这可能和你熟悉的所有编 ...

  6. spring boot 配置Rabbit

    单独安装Rabbit服务并设置启动,可以通过浏览器访问,一般访问地址是http://localhost:15672/ ,用户名密码看配置文件的用户名密码 1 实例化配置类注解 import org.s ...

  7. ios宏定义字符串

    ios宏定义字符串 #define objcString(str) @""#str"" 使用效果: objcString(字符串)

  8. 添加一个js扩展方法

    String.prototype.repeatify=String.prototype.repeatify || function(times){ var str=''; for(var i=0;i& ...

  9. 在vscode中使用webpack中安装的echarts文件失败,dom获取class名,图表不显示

    所有的东西都是新学的,所以遇到了很多问题: (1)首先,在电脑上已经安装了node的情况下, 在npm中安装echarts:npm install echarts --save mac系统在最前面加上 ...

  10. Ajax中异步与同步的区别

    同步可以解决,只有前一个请求结束后,当前请求才会发起.