要实现的操作是插入,删除,找到比指定值大的,小的值操作。

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相关推荐

  1. HYSBZ - 1208 宠物收养所(Splay)

    题目链接:点击查看 题目大意:中文题 题目分析:一个星期前用单旋splay写的,一直TLE,一气之下用set乱搞写过去了,今天突然想起来这个题,意识到会不会是单旋的问题,改成双旋立马AC,而且比set ...

  2. BZOJ 1208: [HNOI2004]宠物收养所 (Treap)

    BZOJ 1208: [HNOI2004]宠物收养所 题目概述: 有一家宠物收养所,提供两种服务:收养主人遗弃的宠物和让新主人领养宠物. 宠物收养所中总是会有两种情况发生:遗弃宠物过多和领养宠物人过多 ...

  3. 【渝粤题库】国家开放大学2021春2757宠物饲养题目

    试卷代号:2757 2021年春季学期期末统一考试 宠物饲养 试题 2021年7月 一.单项选择题(每小题3分,共15分) 1.下列选项中的描述不属于母猫发情表现的是( ). A.外出游荡.大声叫唤 ...

  4. html5做宠物饲养,说一说最适合上班族养的十大宠物

    1.猫 虽然传统宠物猫和狗看起来都不太适合上班族饲养,但maigoo小编这里还是想要推荐一下--养一只猫吧.猫猫与狗狗绝对是一个有爱心人士最好的伴侣,但奈何上班族朝九晚五,一是不太好照顾,二是会长时间 ...

  5. 智能宠物饲养系统设计

    word完整版可点击如下下载>>>>>>>> 智能宠物饲养系统设计.rar-其它文档类资源-CSDN下载1.资源内容:毕业设计lun-wenword版1 ...

  6. BZOJ 1208: [HNOI2004]宠物收养所

    1208: [HNOI2004]宠物收养所 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 7684  Solved: 3042 [Submit][S ...

  7. BZOJ 1208 [HNOI2004]宠物收养所 treap

    题意: 太长了不好概括自己看吧. 解析: 显然这有查找前驱后继的操作. 直接上treap就行,复杂度也放的很宽 但是我们要记录treap里当前存的是宠物还是领养人即可. 讨论一下就是sb题了. 代码: ...

  8. NHOI 2004 宠物收养所 splay解法

    1208: [HNOI2004]宠物收养所 Time Limit: 10 Sec   Memory Limit: 162 MB Submit: 3047   Solved: 1098 [ Submit ...

  9. BZOJ 1861 ZJOI2006 Book 书架 Splay

    题目大意:--自己看懒得打了 很裸的Splay 首先开一个指针数组记录每个值代表的节点 然后就能找到某本书在序列中的什么位置了 总感觉这题可以不用Splay的说--一定是我的错觉 样例中居然尼玛有中文 ...

最新文章

  1. 如何使用 UserAccountControl 标志操纵用户帐户属性
  2. 中大博士分析ICLR 2022投稿趋势:Transformer激增,ViT首进榜单前50,元学习大跌
  3. Java开发环境变量配置【java1.8安装及环境变量详细配置】【JAVA_HOME系统变量、CLASSPATH系统变量、系统环境变量Path】
  4. 前端学习(1899)vue之电商管理系统电商系统之渲染添加用户的表单
  5. mybatis学习(16):不使用接口的方式
  6. 孙鑫MFC笔记之十七--HOOK编程
  7. HBASE元数据及数据读取过程
  8. comsol官方案例学习——1、有限板上的热传导
  9. 元进Python(3)---如何实现IP子网掩码计算器功能?
  10. 四元数与欧拉角(Yaw、Pitch、Roll)的转换
  11. 最小二乘法曲线拟合以及Matlab实现
  12. 云电脑服务:技术与商业模式双重创新
  13. 微软超融合私有云测试05-Hyper-V故障转移群集部署
  14. 【Linux云计算架构:第三阶段-Linux高级运维架构】第26章——tcp三次握手四次挥手及在局域网中使用 awl伪装MAC地址进行多线程SYN攻击
  15. 云原生爱好者周刊:Grafana Loki 免费电子书
  16. 性能测试基础——内存
  17. PostgreSQL对汉字按拼音排序
  18. Discuz!教程之当插件、门户或自定义页面设置成首页时手机版访问跳转到forum.php?mobile=yes的问题
  19. 四川多多开店:拼多多商家绑定银行卡怎么绑定
  20. <2021SC@SDUSC>博客(5)山东大学软件工程应用与实践JPress代码分析(四)

热门文章

  1. 邪恶的三位一体:机器学习、黑暗网络和网络犯罪
  2. elasticsearch 基础语句
  3. 关于极光IM设置昵称不生效的解决办法
  4. 理解MySQL——并行数据库与分区(Partition)
  5. 软件构架实践读书笔记二
  6. 浅析JQuery中的html(),text(),val()区别
  7. IOS-开发中手势的处理
  8. 国际:什么是程序员的优秀品质
  9. 专业程序员成长之路之基础基础!
  10. Android selector 使用