HNOI2017 spaly题解
来源:互联网 发布:矩阵论教学视频百度云 编辑:程序博客网 时间:2024/06/05 00:43
终于调过了,决定把这份巨屎无比的冗长代码贴上来
解题思路:
主要在于发现两个题目的性质:
1.对于插入操作,插入的元素只可能作为他前驱的右儿子或者后继的左儿子
2.旋转最大最小值,并不会改变树的结构,实质上就是把要删除的那个元素直接提到根节点(模拟即可证明)
有了这两条性质,我们可以发现只需要维护这棵树的形态并能够在log内的复杂度求树上某个点的深度
于是我们就可以想到用LCT(有删除操作)。
恰好LCT又是以深度为key值建树,所以我们只需要再维护原树的父子关系,便于LCT的link-cut,这个可以用set维护(找前驱后继),然后每次相当于询问每个点到根节点的距离,又变成模板了
代码细节很多,还要注意这是一棵有根树,还要维护根节点是谁
代码:
#include<bits/stdc++.h>#define ll long long#define mm(a, b) memset(a, b, sizeof(a))#define For(i, a, b) for(int i = (a);i <= (b); ++i)#define rep(i, a, b) for(int i = (a);i >= (b); --i)#define gnn cerr << "GNN睡着了" << endl;using namespace std;const int inf = 1e9 + 1;int read(){ int sum = 0, fg = 1; char c = getchar(); while(c < '0' || c > '9'){if(c == '-')fg = -1;c = getchar();} while(c >='0' && c <='9')sum = (sum << 1) + (sum << 3) + c-'0', c = getchar(); return sum * fg;}const int maxn = 200010;void file(){#ifndef ONLINE_JUDGE freopen("ai.in", "r", stdin); freopen("ai.out", "w", stdout);#endif}map<int , int> q;int m, tree[maxn], val[maxn], ch[maxn][2], rev[maxn], cnt, fa[maxn];bool isroot(int h){return ch[fa[h]][0] != h && ch[fa[h]][1] != h;}void pushup(int h){tree[h] = 1; tree[h] += tree[ch[h][0]] + tree[ch[h][1]];}void pushdown(int h){ if(!rev[h]) return; rev[h] = 0; swap(ch[h][0], ch[h][1]); if(ch[h][0]) rev[ch[h][0]] ^= 1; if(ch[h][1]) rev[ch[h][1]] ^= 1;}void PUSHDOWN(int h){ if(!isroot(h)) PUSHDOWN(fa[h]); pushdown(h);}void rotate(int h){ int father = fa[h], grandfa = fa[father]; bool w = (ch[father][1] == h); fa[ch[h][w^1]] = father; ch[father][w] = ch[h][w^1]; fa[father] = h; ch[h][w^1] = father; fa[h] = grandfa; if(ch[grandfa][0] == father) ch[grandfa][0] = h; else if(ch[grandfa][1] == father) ch[grandfa][1] = h; pushup(father), pushup(h);}bool pd(int h){return ch[fa[h]][0] == h;}void splay(int h){ PUSHDOWN(h); while(!isroot(h)){ if(!isroot(fa[h]) && pd(h) == pd(fa[h])) rotate(fa[h]); rotate(h); }}void access(int h){ int y = 0; while(h){ splay(h); ch[h][1] = y; pushup(h); y = h; h = fa[h]; }}void makeroot(int h){ access(h); splay(h); rev[h] ^= 1;}void cut(int x,int y){ makeroot(x); access(y); splay(y); fa[x] = ch[y][0] = 0;}void link(int x,int y){ makeroot(x); fa[x] = y;}void Get(){ m = read();}int zf = 0, nowroot, truelyfa[maxn], truelych[maxn][2];int get_dep(int h){ makeroot(nowroot); access(h); splay(h); return tree[h];}set<int> Set;set<int>::iterator it, other;int nowyuansu, flag = 0;void _Min(int type){ it = Set.begin(); int Min = *it; int id = q[Min]; printf("%d\n", get_dep(id)); if(type == 1) nowyuansu = Min; if(id == nowroot) {flag = 1; return;} if(truelych[id][1]) cut(truelych[id][1], id); if(truelyfa[id]){ cut(truelyfa[id], id); int father = truelyfa[id]; truelych[father][0] = truelych[id][1]; if(truelych[id][1]){ truelyfa[truelych[id][1]] = father; link(truelych[id][1], father); } } truelyfa[id] = 0; if(nowroot == id){ if(truelych[id][1]){ link(id, truelych[id][1]); truelyfa[truelych[id][1]] = id; } } else{ truelych[id][1] = nowroot; truelyfa[nowroot] = id; link(id, nowroot); } nowroot = id; makeroot(nowroot);}void _Max(int type){ it = Set.end(); -- it; int Max = *it; int id = q[Max]; printf("%d\n", get_dep(id)); if(type == 1) nowyuansu = Max; if(id == nowroot) {flag = 1; return;} if(truelych[id][0]) cut(truelych[id][0], id); if(truelyfa[id]){ cut(truelyfa[id], id); int father = truelyfa[id]; truelych[father][1] = truelych[id][0]; if(truelych[id][0]){ truelyfa[truelych[id][0]] = father; link(truelych[id][0], father); } } truelyfa[id] = 0; if(nowroot == id){ if(truelych[id][0]){ link(id, truelych[id][0]); truelyfa[truelych[id][0]] = id; } } else{ truelych[id][0] = nowroot; truelyfa[nowroot] = id; link(id, nowroot); } nowroot = id; makeroot(nowroot);}void solve(){ while(m --){ int type = read(); if(type == 1){ int x = read(); ++ cnt; q[x] = cnt; zf ++; if(zf == 1) nowroot = cnt; int pre = inf; it = Set.lower_bound(x); if(it != Set.begin()) --it, pre = *it; other = Set.upper_bound(x); int suf = inf; if(other != Set.end()) suf = *other; Set.insert(x); int ans = 1; if(pre != inf && suf != inf){ int ans1 = get_dep(q[pre]), ans2 = get_dep(q[suf]); makeroot(nowroot); if(get_dep(q[pre]) < get_dep(q[suf])){ fa[cnt] = q[suf]; truelyfa[cnt] = q[suf]; truelych[q[suf]][0] = cnt; ans = ans2 + 1; } else{ fa[cnt] = q[pre]; truelyfa[cnt] = q[pre]; truelych[q[pre]][1] = cnt; ans = ans1 + 1; } } else if(pre != inf){ int ans1 = get_dep(q[pre]); makeroot(nowroot); fa[cnt] = q[pre]; truelyfa[cnt] = q[pre]; truelych[q[pre]][1] = cnt; ans = ans1 + 1; } else if(suf != inf){ int ans2 = get_dep(q[suf]); makeroot(nowroot); fa[cnt] = q[suf]; truelyfa[cnt] = q[suf]; truelych[q[suf]][0] = cnt; ans = ans2 + 1; } printf("%d\n", ans); } else if(type == 2){ _Min(0); } else if(type == 3){ _Max(0); } else if(type == 4){ flag = 0; _Min(1); if(flag && zf != 1){ cut(nowroot, truelych[nowroot][1]); truelyfa[truelych[nowroot][1]] = 0; nowroot = truelych[nowroot][1]; } else if(zf != 1){ cut(nowroot, truelych[nowroot][1]); nowroot = truelych[nowroot][1]; truelyfa[nowroot] = 0; } -- zf; makeroot(nowroot); Set.erase(nowyuansu); } else{ flag = 0; _Max(1); if(flag && zf != 1){ cut(nowroot, truelych[nowroot][0]); truelyfa[truelych[nowroot][0]] = 0; nowroot = truelych[nowroot][0]; } else if(zf != 1){ cut(nowroot, truelych[nowroot][0]); nowroot = truelych[nowroot][0]; truelyfa[nowroot] = 0; } --zf; makeroot(nowroot); Set.erase(nowyuansu); } }}int main(){ file(); Get(); solve(); return 0;}
阅读全文
1 0
- HNOI2017 spaly题解
- [spaly模拟 线段树] BZOJ 4825 [Hnoi2017]单旋
- [题解]bzoj4826 HNOI2017 影魔
- [题解]bzoj4825 HNOI2017单旋
- Spaly学习
- HNOI2017滚粗记
- HNOI2017滚粗记
- hnoi2017滚粗记
- [HNOI2017]影魔
- HNOI2017 影魔
- HNOI2017 礼物
- HNOI2017总结
- UVA 11922 Permutation Transformer [Spaly]
- HNOI2017滚粗记退役记
- HNOI2017退役记
- BZOJ4825 [Hnoi2017]单旋
- BZOJ4826 [Hnoi2017]影魔
- BZOJ4827 [Hnoi2017]礼物
- 《JAVA编程技巧1001条》第334条:数学函数 求绝对值.
- 动态给src赋值
- 【java基础】流程控制和数组
- 在指定的浏览器运行angular2 APP
- codeforce898E Squares and not squares (round #451 div 2)
- HNOI2017 spaly题解
- SSM+R之MyBatis基础问答
- 第26章 编写应用程序交叉编译
- Mybatis_HelloWord
- app适配js
- Java注解介绍
- Python+pandas实现时间序列数据扩展案例一则
- AutoCAD .Net 创建点Point
- 从今天开始,每天花1小时学习Python,附电子书