BZOJ 1588 营业额统计 (Splay Tree)
来源:互联网 发布:豆瓣淘宝卖家讨论区 编辑:程序博客网 时间:2024/04/30 06:38
题目大意:
中文题面= =
大致思路:
作为初学Splay的第一道练习题.....
使用到的操作:
1.在原序列末尾插入新元素, 键值不出现重复
2. 寻找比某个键值小或者大的最近的键值, 通过Splay转为求根节点的前驱和后继
代码如下:
Result : Accepted Memory : 2836 KB Time : 140 ms
/* * Author: Gatevin * Created Time: 2015/8/21 15:30:30 * File Name: Sakura_Chiyo.cpp */#include<iostream>#include<sstream>#include<fstream>#include<vector>#include<list>#include<deque>#include<queue>#include<stack>#include<map>#include<set>#include<bitset>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<cctype>#include<cmath>#include<ctime>#include<iomanip>using namespace std;const double eps(1e-8);typedef long long lint;struct Splay_Tree{#define maxn 100010 int pre[maxn];//u父亲节点是pre[u] int key[maxn];//键值 int next[maxn][2];//next[u][0]是结点u的左子树, next[u][1]是u的右子树 int root;//当前的根节点 int tot;//总的结点数量 void newnode(int &r, int father, int value)//新建结点, 父亲是father, 键值为value { r = ++tot; pre[r] = father; key[r] = value; next[r][0] = next[r][1] = 0;//新节点r的左右子树为空 return; } //旋转, kind = 1表示右旋, kind = 0表示左旋 void Rotate(int x, int kind) { int y = pre[x]; next[y][!kind] = next[x][kind]; pre[next[x][kind]] = y; if(pre[y]) next[pre[y]][next[pre[y]][1] == y] = x; pre[x] = pre[y]; next[x][kind] = y; pre[y] = x; return; } //Splay伸展调整, 将根为r的子树调整为goal, (将r所在子树调整为goal的左或者右子树 void Splay(int r, int goal)//goal为0会旋转至根节点, pre[root] = 0 { //旋转会使得r的父亲是goal while(pre[r] != goal) { if(pre[pre[r]] == goal)//只需要进行一次Zig或者Zag操作即可 Rotate(r, next[pre[r]][0] == r);//r是左子树就右旋, 否则左旋 else { int y = pre[r]; int kind = next[pre[y]][0] == y;//y是否是左子树 if(next[y][kind] == r)//y左r右或者 y右r做, 说明要进行Zig-Zag或者Zag-Zig操作 { Rotate(r, !kind); Rotate(r, kind); } else//y, r都是左子树或者都是右子树, 进行Zig-Zig或者Zag-Zag操作 { Rotate(y, kind); Rotate(r, kind); } } } if(goal == 0) root = r; } int insert(int k)//插入一个键值k { int r = root; while(next[r][key[r] < k]) { if(key[r] == k)//重复元素, 不插入 { Splay(r, 0);//将r旋转至根节点 return 0;//插入失败 } r = next[r][key[r] < k]; } newnode(next[r][k > key[r]], r, k); Splay(next[r][k > key[r]], 0);//将新插入的结点旋转至根 return 1;//插入成功 } //寻找结点编号为x的结点的前驱结点, 即左子树的最右结点 int getPre(int x)//返回结点编号, -1表示没有 { int tmp = next[x][0]; if(tmp == 0) return -1; while(next[tmp][1]) tmp = next[tmp][1]; return tmp;// } //寻找结点编号为x的结点的后继结点, 即右子树的最左结点 int getNext(int x)//返回结点编号, 编号为-1表示没有 { int tmp = next[x][1]; if(tmp == 0) return -1; while(next[tmp][0]) tmp = next[tmp][0]; return tmp; }};Splay_Tree tree;int n;const int inf = 1e9 + 7;int main(){ while(~scanf("%d", &n)) { tree.root = tree.tot = 0; int ans = 0; for(int i = 1; i <= n; i++) { int num; if(scanf("%d", &num) == EOF) num = 0;//莫名的奇怪判断... if(i == 1) { ans += num; tree.newnode(tree.root, 0, num); continue; } if(tree.insert(num) == 0) continue;//重复值 //由于进行了insert操作num一定在根的位置 int tmp = inf; int a = tree.getPre(tree.root); int b = tree.getNext(tree.root); if(a != -1) tmp = min(tmp, tree.key[tree.root] - tree.key[a]); if(b != -1) tmp = min(tmp, tree.key[b] - tree.key[tree.root]); ans += tmp; } printf("%d\n", ans); } return 0;}
0 0
- BZOJ 1588 营业额统计 (Splay Tree)
- bzoj 1588 营业额统计 splay
- BZOJ 1588 营业额统计 Splay
- BZOJ 1588 营业额统计 Splay
- BZOJ 1588 营业额统计 Splay
- bzoj 1588 hnoi2002营业额统计 splay
- bzoj 1588 [HNOI2002]营业额统计 splay
- 【Splay】BZOJ 1588 [HNOI2002]营业额统计
- [BZOJ 1588]营业额统计 && splay部分模版
- bzoj 1588 [HNOI2002]营业额统计 splay
- BZOJ 1588 [HNOI 2002] 营业额统计 Splay
- bzoj 1588: [HNOI2002]营业额统计 splay
- Bzoj 1588: [HNOI2002]营业额统计(splay)
- BZOJ 1588 [HNOI2002] 营业额统计 [splay做法]
- splay bzoj 1588 营业额统计(HNOI 2002)
- BZOJ 1588 [HNOI2002]营业额统计(Splay)
- bzoj #1588 营业额统计(splay)
- BZOJ 题目1588: [HNOI2002]营业额统计(Splay Tree 求前驱后继)
- break 的一个“高级用法”
- fragment的问题
- 那些猥琐的Java笔试题集锦(持续更新)
- 260 Single Number III
- 获取Json文件的方法
- BZOJ 1588 营业额统计 (Splay Tree)
- 堆(heap)和栈(stack)有什么区别??
- OpenGL介绍
- Atitit.软件开发的最终的设计 dsl化,ast化(建立ast, 解析执行ast)
- WebSocket(1)-- WebSocket API简介
- POJ 1002 487-3279 水
- 如何成为一名教练型领导者
- java Swing设置无限大
- 在上传文件时限制上传文件的大小,并捕捉超过文件大小限制的异常