(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 ...
随机推荐
- c#基础: 线程的初级用法总结
启动一个线程的两种方法: a.使用无参的方法 Thread thread1 = new Thread(new ThreadStart("调用的方法名")): ...
- Linux目录和权限
1. rmdir -p 用来删除一串目录,是否可以成功删除? rmdir -p 删除一个不存在的目录时是否报错呢?rmdir -p 不能成功删除非空目录,rmdir -p 删除一个不存在的目录 ...
- 如何判断Linux load的值是否过高
1.先使用top看下CPU占用高的进程,找出进程的进程ID(pid): 查看方法:top 2.根据进程ID(pid)查看是进程的那些线程占用CPU高. 查看方法:top -Hp pid 3.使用pst ...
- <!DOCTYPE html>的问题
<!DOCTYPE> 声明必须位于 HTML5 文档中的第一行,也就是位于 <html> 标签之前.该标签告知浏览器文档所使用的 HTML 规范. doctype 声明不属于 ...
- 分页搜索查询sql
select * from (select t.*,rownum no from " + table + " t where scbj=0)where (no>(" ...
- C#调用C++的DLL 数据类型转换
/C++中的DLL函数原型为 //extern "C" __declspec(dllexport) bool 方法名一(const char* 变量名1, unsig ...
- Arc engine - Geodatabase.
Geodatabase以层次结构的数据对象来组织地理数据. 这些数据对象存储在要素类(Feature Classes).对象类(0bject classes)和数据集(Feature datasets ...
- JedisPool操作
Jedis 使用 commons-pool 完成池化实现. 先做个配置文件(properties文件): #最大分配的对象数 redis.pool.maxActive=1024 #最大能够保持idel ...
- 关于(x&y)+((x^y)>>1)的探究
今天在程序员面试宝典上看到 int f(int x int y ) { return (x&y)+((x^y)>>1) } f(729,271) 结果为500 从式子中可以看出分为 ...
- $.unique() 对象组成的数组去掉重复对象
发现一件事,一个完全由对象组成的数组,用$.unique()方法去掉重复的时候不管用 var arr = [{text:'第一个',value:'1'},{text:'第二个',value:'2'}, ...