博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ 1588:营业额统计(Splay)
阅读量:5086 次
发布时间:2019-06-13

本文共 2614 字,大约阅读时间需要 8 分钟。

题意:中文题意。

思路:每一个点每一个点插入Splay,然后插入新的一个点之后,查这个节点的前驱和后继,即左子树最右边的点和右子树最左边的点。然后再从两个点中取个差值较小的就是答案了。要注意Rotate的时候一些细节(要给 rt 的父亲的父亲更新其孩子的值),还有Splay的细节:如果 rt 和 父节点都是要旋转相同方向,应该先旋转父亲节点再旋 rt,如果旋转不同方向就都是旋 rt。

1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 using namespace std; 10 #define INF 0x7fffffff 11 #define N 40000 12 struct node 13 { 14 int val, fa, son[2]; // val是节点权值,fa是父亲,son[0]是左儿子, son[1]是右儿子 15 }tree[N]; 16 int cnt; // 节点数 17 18 void new_node(int f, int w, int kind) 19 { 20 cnt++; 21 memset(tree[cnt].son, 0, sizeof(tree[cnt].son)); 22 tree[cnt].val = w; 23 tree[cnt].fa = f; 24 tree[f].son[kind] = cnt; 25 } 26 27 void Rotate(int rt, int kind) // 旋转操作要注意更新 rt 的父亲的父亲的儿子的值 28 { 29 int y = tree[rt].fa; 30 tree[y].son[kind^1] = tree[rt].son[kind]; 31 if(tree[rt].son[kind] != 0) tree[tree[rt].son[kind]].fa = y; 32 tree[rt].fa = tree[y].fa; 33 int z = tree[rt].fa; 34 if(tree[z].son[0] == y) tree[z].son[0] = rt; // 就是这里 35 else tree[z].son[1] = rt; 36 tree[rt].son[kind] = y; 37 tree[y].fa = rt; 38 } 39 40 void Splay(int rt, int goal) 41 { 42 if(tree[rt].fa == goal) return ; 43 while(tree[rt].fa != goal) { 44 int y = tree[rt].fa; 45 int z = tree[y].fa; 46 int kind1 = rt == tree[y].son[0] ? 1 : 0; 47 int kind2 = y == tree[z].son[0] ? 1 : 0; 48 if(z == goal) { 49 Rotate(rt, kind1); 50 } else { 51 if(kind1 == kind2) { // 连续左旋或者右旋 52 Rotate(y, kind2); 53 } else { 54 Rotate(rt, kind1); // 先左后右或者先右后左 55 } 56 Rotate(rt, kind2); 57 } 58 } 59 } 60 61 void Insert(int rt, int fa, int val, int kind) 62 { 63 if(rt == 0) { 64 new_node(fa, val, kind); 65 return ; 66 } 67 if(tree[rt].val >= val) Insert(tree[rt].son[0], rt, val, 0); 68 else Insert(tree[rt].son[1], rt, val, 1); 69 } 70 71 int Find(int rt, int kind) 72 { 73 if(tree[rt].son[kind] == 0) return rt; // 查先驱和后继节点 74 Find(tree[rt].son[kind], kind); 75 } 76 77 int main() 78 { 79 int n; 80 while(~scanf("%d", &n)) { 81 long long ans = 0; 82 cnt = 0; 83 for(int i = 1; i <= n; i++) { 84 int x; 85 scanf("%d", &x); 86 if(i == 1) { 87 new_node(0, x, 0); 88 ans += x; 89 } else { 90 Insert(cnt, 0, x, 0); 91 Splay(cnt, 0); 92 int pre = 0, suf = 0; 93 pre = Find(tree[cnt].son[0], 1); 94 suf = Find(tree[cnt].son[1], 0); 95 int prev = INF, sufv = INF; 96 if(pre != 0) prev = tree[pre].val; 97 if(suf != 0) sufv = tree[suf].val; 98 ans += min(abs(x - prev), abs(x - sufv)); 99 }100 }101 printf("%lld\n", ans);102 }103 return 0;104 }

 

转载于:https://www.cnblogs.com/fightfordream/p/6053921.html

你可能感兴趣的文章
密码学笔记——培根密码
查看>>
Screening technology proved cost effective deal
查看>>
MAC 上升级python为最新版本
查看>>
创业老板不能犯的十种错误
查看>>
Animations介绍及实例
查看>>
判断请求是否为ajax请求
查看>>
【POJ2699】The Maximum Number of Strong Kings(网络流)
查看>>
spring boot配置跨域
查看>>
BZOJ 1996 合唱队(DP)
查看>>
进击吧!阶乘——大数乘法
查看>>
安卓学习资料推荐-25
查看>>
Mysql数据库备份和还原常用的命令
查看>>
关于退出当前页面在火狐的一些问题
查看>>
【项目实施】项目考核标准
查看>>
spring-aop AnnotationAwareAspectJAutoProxyCreator类
查看>>
经典入门_排序
查看>>
Redis Cluster高可用集群在线迁移操作记录【转】
查看>>
二、spring中装配bean
查看>>
VIM工具
查看>>
javascript闭包
查看>>