(HYSBZ)BZOJ 1588 营业额统计
| Time Limit: 5000MS | Memory Limit: 165888KB | 64bit IO Format: %lld & %llu |
Description
Input
Output
Sample Input
6
5
1
2
5
4
6
Sample Output
12
Hint
结果说明:5+|1-5|+|2-1|+|5-5|+|4-5|+|6-5|=5+4+1+0+1+1=12
Source
/****Spaly的基本操作和应用****
求前驱与root的差和后驱与root的差,取最大,累加即可.
Rotate写的很精简,是学习别人的;
= =!他的源码有错误,不过却又不影响结果......
以后看别人的东西也要小心~~
*****************************/
#include <map>
#include <set>
#include <list>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <vector>
#include <bitset>
#include <cstdio>
#include <string>
#include <numeric>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define eps 1e-8
#define inf 0x7fffffff
#define debug puts("BUG")
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define read freopen("in.txt","r",stdin)
#define write freopen("out.txt","w",stdout)
#define Mem(a,x) memset(a,x,sizeof(a))
#define maxn 100005
int pre[maxn],key[maxn],ch[maxn][2],root,tot1;
//分别表示父结点,键值,左右孩子(0为左孩子,1为右孩子),根结点,结点数量
int n;
int ans;
void init()
{
root=tot1=0;
ans=0;
Mem(key,0);
}
void NewNode(int &r,int father,int k)
{
r=++tot1; //记录新节点的位置
pre[r]=father;//更新新节点的父亲
key[r]=k;
ch[r][0]=ch[r][1]=0;//左孩子和右孩子为空
}
void Rotate(int x,int k)//k为左旋和右旋的标志
{
int y=pre[x];/**记录x的父亲**/
ch[y][!k]=ch[x][k];
pre[ch[x][k]]=y;
/**如果k=0, 表示从左到右旋转;如果k=1,表示从右到左旋转
*k=0, 表示x的位置由它的右孩子代替;
*k=1, 表示x的位置由它的左孩子代替.
*x的位置, 即为 !k
**/
if(pre[y])
ch[pre[y]][ch[pre[y]][1]==y]=x;
pre[x]=pre[y];
/** 更新x的父亲 和 x的新父亲的孩子节点(如果新的父亲存在)
* 如上
**/
ch[x][k]=y;
pre[y]=x;
/**更新y的父亲(即为x) 和 x的孩子节点
*如上
**/
}
void Splay(int r,int goal)//Splay调整,将r的值调整到目标位置goal
{
while(pre[r]!=goal)
{
if(pre[pre[r]]==goal)//如果r的父亲就是根节点,goal的值为0,直接进行一次旋转即可
{
Rotate(r,ch[pre[r]][0]==r);
}
else//否则
{
int y= pre[r];
int k= ch[pre[y]][0]==y;//记录y与y的父亲的方向
if(ch[y][k]==r)//判断x与y和y的父亲是否在同一方向
{
//是 , 进行一字型旋转
Rotate(r,!k);//先左(右)旋
Rotate(r, k);//后右(左)旋
}
else
{
//否 , 进行之字形旋转
Rotate(y,k);//先对y进行左(右)旋
Rotate(r,k);//后对x进行右(左)旋
}
}
}
/**更新根节点**/
if(goal==0) root=r;
}
int Insert(int k) //将键值k插入到Splay中(Splay不为空)
{
int r=root; //从根节点开始
while(ch[r][key[r]<k])
{
//一直向下,找到叶子节点,根据二叉排序树的性质,查找时只需要比较key[r]与k的大小
if(key[r]==k)
{
//同一个值不需要再次插入,只需要进行Splay操作
Splay(r,0);
return 0; //表示插入失败
}
r=ch[r][key[r]<k]; //未找到叶子节点,就需继续向下找
}
if(key[r]==k)
{
//同一个值不需要再次插入,只需要进行Splay操作
Splay(r,0);
return 0; //表示插入失败
}
NewNode(ch[r][k>key[r]],r,k); //新建节点
Splay(ch[r][k>key[r]],0); //Slay操作,插入的节点调整至根节点
return 1; //表示插入成功
}
int Get_pre(int x)//寻找前驱,即寻找左子树的最右点
{
int temp=ch[x][0];
if(temp==0) return inf;
while(ch[temp][1])
temp=ch[temp][1];
return key[x]-key[temp];
}
int Get_next(int x)//寻找后继,即寻找右子树的最左点
{
int temp=ch[x][1];
if(temp==0) return inf;
while(ch[temp][0])
temp=ch[temp][0];
return key[temp]-key[x];
}
/********************DEBUG***************************/
void Puts()
{
printf("root: %d\n",root);
for(int i=1;i<=tot1;i++)
{
printf("node: %d ,l is %d ,r is %d ,key : %d\n",i,ch[i][0],ch[i][1],key[i]);
}
}
/********************DEBUG END***********************/
int main()
{
while(~scanf("%d",&n))
{
init();
for(int i=1; i<=n; i++)
{
int x;
scanf("%d",&x);
if(i==1)
{
ans+=x;
NewNode(root,0,x);//建立Splay的第一个节点
continue;
}
if(Insert(x)==0)//插入,已经存在的值不需要插入
{continue;}
int a=Get_pre(root);//与前驱的差,可能不存在
int b=Get_next(root);//与后驱的差,也可能不存在
ans+=min(a,b);
}
printf("%d\n",ans);
}
return 0;
}
(HYSBZ)BZOJ 1588 营业额统计的更多相关文章
- BZOJ 1588 营业额统计
Description 营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来每 ...
- BZOJ 1588 营业额统计 set
题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1588 题目大意: 营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交 ...
- bzoj 1588营业额统计(HNOI 2002)
http://www.lydsy.com/JudgeOnline/problem.php?id=1588 splay bottom-up的数组实现. 题意就是给你一组数,求每个数与在其前面且与其最相 ...
- BZOJ 1588 营业额统计 Splay
主要操作为Splay中插入节点,查找前驱和后继节点. 1: #include <cstdio> 2: #include <iostream> 3: #include <c ...
- [bzoj] 1588 营业额统计 || Splay板子题
原题 给出一个n个数的数列ai ,对于第i个元素ai定义\(fi=min(|ai-aj|) (1<=j<i)\),f1=a1,求\(/sumfi\) Splay板子题. Splay讲解:h ...
- HYSBZ - 1588 营业额统计 (伸展树)
题意:营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额.分析营 ...
- HYSBZ 1588 营业额统计
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1588 题意:详见题面,中文 思路:平衡树的模板题. 可用Treap,Splay,Scape ...
- HYSBZ 1588 营业额统计 (Splay树)
题意:给出一个公司每一天的营业额,求每天的最小波动值之和.该天的最小波动值= min { 绝对值| 该天以前某一天的营业额-该天的营业额 | }.第一天的最小波动值就是其自己. 思路:Splay伸展树 ...
- BZOJ 1588: [HNOI2002]营业额统计 双向链表
BZOJ 1588: [HNOI2002]营业额统计 Time Limit: 5 Sec Memory Limit: 512 MBSubmit: 9619 Solved: 3287 题目连接 ht ...
随机推荐
- angularjs基本执行流程
近期温习了下angularjs执行流程,备记下.以便查看. 主要的执行流程例如以下: 1.用户请求应用起始页. 2.用户的浏览器向server发起一次HTTP连接,然后载入index.html页面,这 ...
- BNU10791:DOTA选人
DOTA(Defense of the Ancients)是一款很受欢迎的游戏.DOTA将10个游戏玩家分为两组,分别为天灾和近卫,推倒对方主基地的一方获得胜利.每个玩家可以选择一个英雄作为游戏中的角 ...
- Qt 图形特效(Graphics Effect)介绍
原文链接:Qt 图形特效(Graphics Effect)介绍 QGraphicsEffect也是Qt-4.6引入的一个新功能.它让给图形元素QGraphicsItem增加更佳视觉效果的编程变得非常简 ...
- JSP实现分页功能
分页须知知识点: (1)JDBC2.0的可滚动结果集. (2)HTTP GET请求. 一.可滚动结果集 Connection con = DriverManager.getConnection( ...
- mysql高可用方案MHA介绍
mysql高可用方案MHA介绍 概述 MHA是一位日本MySQL大牛用Perl写的一套MySQL故障切换方案,来保证数据库系统的高可用.在宕机的时间内(通常10-30秒内),完成故障切换,部署MHA, ...
- Csharp 高级编程 C7.1.2
第七章 代理(1) 一.代理要声明 二.代理使用步骤 声明代理 初始化代理(使用 实例的方法名 作为参数) 使用代理 代码示例: /*C7.1.2*/ using System; using Syst ...
- C#读取XML配置文件
DataSource.xml文件,要放在bin/debug/目录下: <?xml version="1.0" encoding="utf-8" ?> ...
- mvc actionresult 判断是否回发?
if(Request.HttpMethod.Equals("POST", StringComparison.OrdinalIgnoreCase)){POST回发的代码}
- 线段树练习 codevs 1080
/* codevs 1080 线段树练习 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description 一行N个方格,开 ...
- js页面加载进度条
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...