[HNOI2002]营业额统计 (Splay || Treap)
2016-01-07 13:43
288 查看
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1588
题意:
Submit: 11846 Solved: 4226
[Submit][Status][Discuss]
该天的最小波动值 当最小波动值越大时,就说明营业情况越不稳定。 而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。 第一天的最小波动值为第一天的营业额。 输入输出要求
5
1
2
5
4
6
此题数据有问题,详见讨论版http://www.lydsy.com/JudgeOnline/wttl/wttl.php?pid=1588
[Submit][Status][Discuss]
HOME Back
分析:用什么都可以做。。。主要是为了入门Splay。下面给出splay和treap的代码,一起练,两个的速度差不多。
Splay代码:
Treap代码:
题意:
1588: [HNOI2002]营业额统计
Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 11846 Solved: 4226
[Submit][Status][Discuss]
Description
营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。 Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况:该天的最小波动值 当最小波动值越大时,就说明营业情况越不稳定。 而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。 第一天的最小波动值为第一天的营业额。 输入输出要求
Input
第一行为正整数 ,表示该公司从成立一直到现在的天数,接下来的n行每行有一个整数(有可能有负数) ,表示第i天公司的营业额。Output
输出文件仅有一个正整数,即Sigma(每天最小的波动值) 。结果小于2^31 。Sample Input
65
1
2
5
4
6
Sample Output
12HINT
结果说明:5+|1-5|+|2-1|+|5-5|+|4-5|+|6-5|=5+4+1+0+1+1=12此题数据有问题,详见讨论版http://www.lydsy.com/JudgeOnline/wttl/wttl.php?pid=1588
Source
[Submit][Status][Discuss]
HOME Back
分析:用什么都可以做。。。主要是为了入门Splay。下面给出splay和treap的代码,一起练,两个的速度差不多。
Splay代码:
#include <bits/stdc++.h> using namespace std; typedef long long LL; typedef unsigned long long ULL; const LL INF = 1E9+9; const int MI = ~0u>>1; const int maxn = 1e6+7; int son[maxn][2],fa[maxn],key[maxn]; // int root,cnt; //根节点和使用节点个数 void Init() { root=0; //0为虚节点 cnt=0; } void newnode(int &r,int f,int v) { r = ++cnt; fa[r]=f; son[r][0]=son[r][1]=0; key[r]=v; } void Rotate(int x,int kind) //kind==1为右旋,kind==0为左旋 { int y=fa[x]; son[y][kind^1]=son[x][kind]; fa[son[x][kind]] = y; if(fa[y]!=0) //虚节点没有孩子 son[fa[y]][son[fa[y]][1]==y] = x; fa[x]=fa[y]; son[x][kind]=y; fa[y]=x; } void Splay(int r,int goal) //将r旋转到goal的下面 { while(fa[r]!=goal) { if(fa[fa[r]] == goal) Rotate(r,son[fa[r]][0]==r); //是左孩子的话就右旋 else { int y=fa[r]; int kind=son[fa[y]][0]==y; //保存y是左孩子还是右孩子 if(son[y][kind]==r) //判断r的方向与y是否一致 { Rotate(r,kind^1); Rotate(r,kind); } else //一致 { Rotate(y,kind); Rotate(r,kind); } } } if(0==goal) root=r; } void Insert(int v) { int r=root; if(r==0) { newnode(root,0,v); return ; } while(son[r][v>key[r]]) r=son[r][v>key[r]]; newnode(son[r][v>key[r]],r,v); Splay(son[r][v>key[r]],0); } int get_pre(int r) //得到r的前继 { if(!son[r][0]) return -MI; r=son[r][0]; while(son[r][1]!=0) r=son[r][1]; return r; } int get_next(int r) { if(!son[r][1]) return -MI; r=son[r][1]; while(son[r][0]!=0) r=son[r][0]; return r; } int main() { int n; while(scanf("%d",&n)!=EOF&&n) { Init(); int ans=0; for(int i=1;i<=n;i++) { int x; if(scanf("%d",&x) == EOF) x= 0; Insert(x); int temp=MI; int a=get_pre(root); if(a!=-MI) temp = min(temp,abs(x-key[a])); int b=get_next(root); if(b!=-MI) temp = min(temp,abs(x-key[b])); ans+=(temp==MI?x:temp); } printf("%d\n",ans); } return 0; }
Treap代码:
#include <bits/stdc++.h> using namespace std; typedef long long LL; typedef unsigned long long ULL; const LL INF = 1E9+9; const int MI = ~0u>>1; struct node //定义Treap节点 { node* son[2]; //左右子树 int v; //值 int p; //优先级 int sz; //以当前节点为根节点的树的大小 node(int x) { son[0]=son[1]=NULL; v=x; p=rand(); sz=1; } void pushup() //增加或删除节点需要修改子树的sz { sz=1; if(son[0]) sz+=son[0]->sz; if(son[1]) sz+=son[1]->sz; } }; inline int cmp(int a,int b) { if(a==b) return -1; return a>b?0:1; } inline void Rotate(node* &root,int d) //d为0时左旋(右节点向上更新), d为1时右旋(左节点向上更新) { node* k = root->son[d^1]; root->son[d^1] = k->son[d] ; k->son[d] = root; root->pushup(); k->pushup(); root = k ; } void Insert(node* &root,int x) { if(NULL==root) root = new node(x); else { int d = root->v>x?0:1; //这样写的话支持相同元素插入 Insert(root->son[d],x); if(root->p<root->son[d]->p) Rotate(root,d^1); } if(root) root->pushup(); } void Destroy(node* &root) { if(root->son[0]) Destroy(root->son[0]); if(root->son[1]) Destroy(root->son[1]); delete root; root=NULL; } int get_pre(node* root,int x) { int ret=-MI; while(root) { if(root->v==x) return x; if(root->v>x) root=root->son[0]; else { ret=max(ret,root->v); root=root->son[1]; } } return ret; } int get_next(node *root,int x) { int ret=MI; while(root) { if(root->v==x) return x; if(root->v<x) root=root->son[1]; else { ret=min(ret,root->v); root=root->son[0]; } } return ret; } int main() { int n; while(scanf("%d",&n)!=EOF&&n) { node* root=NULL; int ans=0; for(int i=1;i<=n;i++) { int x; if(scanf("%d",&x) == EOF) x= 0; int temp=MI; int a=get_pre(root,x); if(a!=MI && a!=-MI) temp = min(temp,abs(x-a)); int b=get_next(root,x); if(b!=MI && b!=-MI) temp = min(temp,abs(x-b)); ans+=(temp==MI?x:temp); Insert(root,x); } printf("%d\n",ans); Destroy(root); } return 0; }
相关文章推荐
- 数据结构之Treap详解
- Treap(树堆)
- NOI2005 维修数列
- [bzoj1500][NOI2005]维修数列
- [bzoj1208] [HNOI2004]宠物收养所
- [bzoj1269][AHOI2006]文本编辑器editort
- [bzoj1503][NOI2004]郁闷的出纳员
- [BZOJ1014][JSOI2008][Splay][RKHash]火星人prefix
- [BZOJ1500][NOI2005][Splay]维修数列
- 初识splay tree ( hihocoder #1034 : 毁灭者问题 题解)
- 初识splay tree (三)
- 初识splay tree (二)
- 区间
- [HNOI 2004]宠物收养所
- [HNOI 2004]宠物收养所
- [NOI 2004]郁闷的出纳员
- [POJ 3580]Super Memo
- Splay树-Codevs 1296 营业额统计
- BZOJ 3223 文艺平衡树 【Splay】
- UVa 1400 "Ray, Pass me the dishes!"(区间最大连续数组和)