BZOJ 1208 宠物饲养所 Splay
要实现的操作是插入,删除,找到比指定值大的,小的值操作。
Splay的删除操作可以是直接用二叉搜索树的删除方式,或者是先将要删除的节点Splay到根,然后找到左子树中最大的节点,将其Splay到根的左儿子位置,此时这个节点必然是没有右子树的,然后直接把他当做根就好。
找大的值可以先找到如果要插入这个值会插在哪里,然后不执行操作,直接找前驱或者后继就可以了。
代码能力捉急,写了整整一天,各种debug蛋疼啊= =
#include <cstdio>
#include <cstring>
#include <climits>
#include <algorithm>using namespace std;const int maxn = 2e6 + 10;
const int mod = 1000000;
const int PET = 0;
const int HUMAN = 1;
const int EMPTY = -1;
const int INF = INT_MAX / 3;
int ch[maxn][2], fa[maxn], val[maxn], sz, root;void rotate(int x, int d) {int y = fa[x];ch[y][d ^ 1] = ch[x][d];fa[ch[x][d]] = y;if (fa[y] != 0) {ch[fa[y]][y == ch[fa[y]][1]] = x;}ch[x][d] = y;fa[x] = fa[y];fa[y] = x;
}int newNode(int &r, int father, int v) {r = ++sz;fa[r] = father; val[r] = v;ch[r][0] = ch[r][1] = 0;return r;
}void splay(int x, int goal) {while (fa[x] != goal) {int y = fa[x], d = val[x] > val[y];if (fa[y] == goal) {rotate(x, d ^ 1);break;}int z = fa[y], d1 = val[y] > val[z];if (d == d1) {rotate(y, d1 ^ 1);rotate(x, d ^ 1);}else {rotate(x, d ^ 1);rotate(x, d1 ^ 1);}}if (goal == 0) {fa[x] = 0;root = x;}
}void debug(int root) {int lc = ch[root][0], rc = ch[root][1];printf("当前节点:%d(val = %d), lch: %d(val = %d), rch %d(val = %d), fa is %d\n",root, val[root], lc, val[lc], rc, val[rc], fa[root]);if (lc) debug(lc);if (rc) debug(rc);
}int insert(int v) {if (root == 0) {newNode(root, 0, v);return root;}int u = root;while (ch[u][v > val[u]] != 0) u = ch[u][v > val[u]];int r = newNode(ch[u][v > val[u]], u, v);splay(r, 0);return r;
}//找后继
int findNext(int x) {//如果x节点有右子树if (ch[x][1] != 0) {//找到右子树中最小的节点int u = ch[x][1];while (ch[u][0] != 0) u = ch[u][0];return u;}//往上寻找int u = x;while (fa[u] != 0 && u != ch[fa[u]][0]) u = fa[u];return fa[u];
}//用二叉搜索树删除节点的方式来删除节点
void remove(int x) {if (ch[x][0] == 0 && ch[x][1] == 0) {if (fa[x] == 0) root = 0;else ch[fa[x]][x == ch[fa[x]][1]] = 0;}else if (ch[x][0] == 0) {if (fa[x] == 0) {root = ch[x][1];fa[ch[x][1]] = 0;}else ch[fa[x]][x == ch[fa[x]][1]] = ch[x][1];fa[ch[x][1]] = fa[x];}else if (ch[x][1] == 0) {if (fa[x] == 0) {root = ch[x][0];fa[ch[x][0]] = 0;}else ch[fa[x]][x == ch[fa[x]][1]] = ch[x][0];fa[ch[x][0]] = fa[x];}else {int r = findNext(x);swap(val[r], val[x]);remove(r);}
}//先splay到根然后删除
void remove_root() {int u = root;if (ch[u][0] == 0) {root = ch[u][1];fa[ch[u][1]] = 0;}else {//找到左子树中最大的值int x = ch[u][0];while (ch[x][1] != 0) x = ch[x][1];//splay到根的做子树splay(x, root);//debug(root);//此时x必然没有右子树,直接作为根ch[x][1] = ch[u][1];if (ch[u][1]) fa[ch[u][1]] = x;root = x; fa[x] = 0;}//debug(root);
}int findValMinNext(int v) {int u = root;while (ch[u][v > val[u]] != 0) u = ch[u][v > val[u]];if (v >= val[u]) return u;while (fa[u] != 0 && val[fa[u]] > val[u]) u = fa[u];return fa[u];
}int findValMaxNext(int v) {int u = root;while (ch[u][v > val[u]] != 0) u = ch[u][v > val[u]];if (v < val[u]) return u;while (fa[u] != 0 && val[fa[u]] <= val[u]) u = fa[u];return fa[u];
}int main() {//freopen("INPUT.002", "r", stdin);//freopen("out.txt", "w", stdout);int n, state, cmd, st, ans;while (scanf("%d", &n) != EOF) {sz = root = ans = 0;state = EMPTY;for (int i = 1; i <= n; i++) {//debug(root);scanf("%d%d", &cmd, &st);if (state == EMPTY) {state = cmd; insert(st);}else if (state == cmd) insert(st);else {val[0] = INF;int g1 = findValMinNext(st), g2 = findValMaxNext(st);//run_test();//printf("g1 is %d, g2 is %d\n", val[g1], val[g2]);int v1 = abs(st - val[g1]), v2 = abs(st - val[g2]);if (v1 <= v2) {ans = (ans + v1) % mod;splay(g1, 0); remove(root);//debug(root);//remove_root();}else {ans = (ans + v2) % mod;splay(g2, 0); //debug(root);remove(root);//remove_root();}if (root == 0) state = EMPTY;}}printf("%d\n", ans);}return 0;
}
转载于:https://www.cnblogs.com/rolight/p/4276783.html
BZOJ 1208 宠物饲养所 Splay相关推荐
- HYSBZ - 1208 宠物收养所(Splay)
题目链接:点击查看 题目大意:中文题 题目分析:一个星期前用单旋splay写的,一直TLE,一气之下用set乱搞写过去了,今天突然想起来这个题,意识到会不会是单旋的问题,改成双旋立马AC,而且比set ...
- BZOJ 1208: [HNOI2004]宠物收养所 (Treap)
BZOJ 1208: [HNOI2004]宠物收养所 题目概述: 有一家宠物收养所,提供两种服务:收养主人遗弃的宠物和让新主人领养宠物. 宠物收养所中总是会有两种情况发生:遗弃宠物过多和领养宠物人过多 ...
- 【渝粤题库】国家开放大学2021春2757宠物饲养题目
试卷代号:2757 2021年春季学期期末统一考试 宠物饲养 试题 2021年7月 一.单项选择题(每小题3分,共15分) 1.下列选项中的描述不属于母猫发情表现的是( ). A.外出游荡.大声叫唤 ...
- html5做宠物饲养,说一说最适合上班族养的十大宠物
1.猫 虽然传统宠物猫和狗看起来都不太适合上班族饲养,但maigoo小编这里还是想要推荐一下--养一只猫吧.猫猫与狗狗绝对是一个有爱心人士最好的伴侣,但奈何上班族朝九晚五,一是不太好照顾,二是会长时间 ...
- 智能宠物饲养系统设计
word完整版可点击如下下载>>>>>>>> 智能宠物饲养系统设计.rar-其它文档类资源-CSDN下载1.资源内容:毕业设计lun-wenword版1 ...
- BZOJ 1208: [HNOI2004]宠物收养所
1208: [HNOI2004]宠物收养所 Time Limit: 10 Sec Memory Limit: 162 MB Submit: 7684 Solved: 3042 [Submit][S ...
- BZOJ 1208 [HNOI2004]宠物收养所 treap
题意: 太长了不好概括自己看吧. 解析: 显然这有查找前驱后继的操作. 直接上treap就行,复杂度也放的很宽 但是我们要记录treap里当前存的是宠物还是领养人即可. 讨论一下就是sb题了. 代码: ...
- NHOI 2004 宠物收养所 splay解法
1208: [HNOI2004]宠物收养所 Time Limit: 10 Sec Memory Limit: 162 MB Submit: 3047 Solved: 1098 [ Submit ...
- BZOJ 1861 ZJOI2006 Book 书架 Splay
题目大意:--自己看懒得打了 很裸的Splay 首先开一个指针数组记录每个值代表的节点 然后就能找到某本书在序列中的什么位置了 总感觉这题可以不用Splay的说--一定是我的错觉 样例中居然尼玛有中文 ...
最新文章
- 如何使用 UserAccountControl 标志操纵用户帐户属性
- 中大博士分析ICLR 2022投稿趋势:Transformer激增,ViT首进榜单前50,元学习大跌
- Java开发环境变量配置【java1.8安装及环境变量详细配置】【JAVA_HOME系统变量、CLASSPATH系统变量、系统环境变量Path】
- 前端学习(1899)vue之电商管理系统电商系统之渲染添加用户的表单
- mybatis学习(16):不使用接口的方式
- 孙鑫MFC笔记之十七--HOOK编程
- HBASE元数据及数据读取过程
- comsol官方案例学习——1、有限板上的热传导
- 元进Python(3)---如何实现IP子网掩码计算器功能?
- 四元数与欧拉角(Yaw、Pitch、Roll)的转换
- 最小二乘法曲线拟合以及Matlab实现
- 云电脑服务:技术与商业模式双重创新
- 微软超融合私有云测试05-Hyper-V故障转移群集部署
- 【Linux云计算架构:第三阶段-Linux高级运维架构】第26章——tcp三次握手四次挥手及在局域网中使用 awl伪装MAC地址进行多线程SYN攻击
- 云原生爱好者周刊:Grafana Loki 免费电子书
- 性能测试基础——内存
- PostgreSQL对汉字按拼音排序
- Discuz!教程之当插件、门户或自定义页面设置成首页时手机版访问跳转到forum.php?mobile=yes的问题
- 四川多多开店:拼多多商家绑定银行卡怎么绑定
- <2021SC@SDUSC>博客(5)山东大学软件工程应用与实践JPress代码分析(四)