题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1588

题意:详见题面,中文

思路:平衡树的模板题。 可用Treap,Splay,Scapegoat Tree

【替罪羊树代码】

#define _CRT_SECURE_NO_DEPRECATE
#include<stdio.h>
#include<string.h>
#include<cstring>
#include<algorithm>
#include<queue>
#include<math.h>
#include<time.h>
#include<vector>
#include<iostream>
using namespace std;
typedef long long int LL;
const int INF = 0x3f3f3f3f;
typedef long long LL;
namespace Scapegoat_Tree {
#define MAXN (1000000 + 10)
const double alpha = 0.75;
struct Node {
Node * ch[];
int key, size, cover; // size为有效节点的数量,cover为节点总数量
bool exist; // 是否存在(即是否被删除)
void PushUp(void) {
size = ch[]->size + ch[]->size + (int)exist;
cover = ch[]->cover + ch[]->cover + ;
}
bool isBad(void) { // 判断是否需要重构
return ((ch[]->cover > cover * alpha + ) ||
(ch[]->cover > cover * alpha + ));
}
};
struct STree {
protected:
Node mem_poor[MAXN]; //内存池,直接分配好避免动态分配内存占用时间
Node *tail, *root, *null; // 用null表示NULL的指针更方便,tail为内存分配指针,root为根
Node *bc[MAXN]; int bc_top; // 储存被删除的节点的内存地址,分配时可以再利用这些地址 Node * NewNode(int key) {
Node * p = bc_top ? bc[--bc_top] : tail++;
p->ch[] = p->ch[] = null;
p->size = p->cover = ; p->exist = true;
p->key = key;
return p;
}
void Travel(Node * p, vector<Node *>&v) {
if (p == null) return;
Travel(p->ch[], v);
if (p->exist) v.push_back(p); // 构建序列
else bc[bc_top++] = p; // 回收
Travel(p->ch[], v);
}
Node * Divide(vector<Node *>&v, int l, int r) {
if (l >= r) return null;
int mid = (l + r) >> ;
Node * p = v[mid];
p->ch[] = Divide(v, l, mid);
p->ch[] = Divide(v, mid + , r);
p->PushUp(); // 自底向上维护,先维护子树
return p;
}
void Rebuild(Node * &p) {
static vector<Node *>v; v.clear();
Travel(p, v); p = Divide(v, , v.size());
}
Node ** Insert(Node *&p, int val) {
if (p == null) {
p = NewNode(val);
return &null;
}
else {
p->size++; p->cover++; // 返回值储存需要重构的位置,若子树也需要重构,本节点开始也需要重构,以本节点为根重构
Node ** res = Insert(p->ch[val >= p->key], val);
if (p->isBad()) res = &p;
return res;
}
}
void Erase(Node *p, int id) {
p->size--;
int offset = p->ch[]->size + p->exist;
if (p->exist && id == offset) {
p->exist = false;
return;
}
else {
if (id <= offset) Erase(p->ch[], id);
else Erase(p->ch[], id - offset);
}
}
public:
void Init(void) {
tail = mem_poor;
null = tail++;
null->ch[] = null->ch[] = null;
null->cover = null->size = null->key = ;
root = null; bc_top = ;
}
STree(void) { Init(); } void Insert(int val) {
Node ** p = Insert(root, val);
if (*p != null) Rebuild(*p);
}
int Rank(int val) { //相同值取最小的排名
Node * now = root;
int ans = ;
while (now != null) { // 非递归求排名
if (now->key >= val) now = now->ch[];
else {
ans += now->ch[]->size + now->exist;
now = now->ch[];
}
}
return ans;
}
int Kth(int k) { //支持相同值
Node * now = root;
while (now != null) { // 非递归求第K大
if (now->ch[]->size + == k && now->exist) return now->key;
else if (now->ch[]->size >= k) now = now->ch[];
else k -= now->ch[]->size + now->exist, now = now->ch[];
}
}
void Erase(int k) {
Erase(root, Rank(k));
if (root->size < alpha * root->cover) Rebuild(root);
}
void Erase_kth(int k) {
Erase(root, k);
if (root->size < alpha * root->cover) Rebuild(root);
}
};
#undef MAXN
}
using namespace Scapegoat_Tree;
STree Scapegoat;
int main(){
#ifdef kirito
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
// int start = clock();
int n,val;
while (~scanf("%d", &n)){
LL sum=;
for (int i = ; i <= n; i++){
scanf("%d", &val);
if (i == ){
sum += val;
}
else{
int valRank = Scapegoat.Rank(val);
int a = abs(Scapegoat.Kth(valRank) - val);
int b = abs(Scapegoat.Kth(valRank - ) - val);
int c = abs(Scapegoat.Kth(val + ) - val);
sum += min(a, min(b, c));
}
Scapegoat.Insert(val);
}
printf("%d\n", sum);
/* DEBUG INFO
vector<Node *> xx;
_t.Travel(_t.root, xx);
cout << "::";
for(int i = 0; i < xx.size(); i++) cout << xx[i]->key << ' '; cout << endl;
*/
}
//#ifdef LOCAL_TIME
// cout << "[Finished in " << clock() - start << " ms]" << endl;
//#endif
return ;
}

【Splay代码】

#define _CRT_SECURE_NO_DEPRECATE
#include<stdio.h>
#include<string.h>
#include<cstring>
#include<algorithm>
#include<queue>
#include<math.h>
#include<time.h>
#include<vector>
#include<iostream>
using namespace std;
typedef long long int LL;
const int MAXN = 1e6 + ;
const int INF = 0x3f3f3f3f;
int cnt, rt;
struct Tree
{
int key, size, fa, son[];
void set(int _key, int _size, int _fa)
{
key = _key;
size = _size;
fa = _fa;
son[] = son[] = ;
}
}T[MAXN]; inline void PushUp(int x)
{
T[x].size = T[T[x].son[]].size + T[T[x].son[]].size + ;
} inline void Rotate(int x, int p)
{
int y = T[x].fa;
T[y].son[!p] = T[x].son[p];
T[T[x].son[p]].fa = y;
T[x].fa = T[y].fa;
if (T[x].fa)
T[T[x].fa].son[T[T[x].fa].son[] == y] = x;
T[x].son[p] = y;
T[y].fa = x;
PushUp(y);
PushUp(x);
} void Splay(int x, int To)
{
while (T[x].fa != To)
{
if (T[T[x].fa].fa == To)
Rotate(x, T[T[x].fa].son[] == x);
else
{
int y = T[x].fa, z = T[y].fa;
int p = (T[z].son[] == y);
if (T[y].son[p] == x)
Rotate(x, !p), Rotate(x, p);
else
Rotate(y, p), Rotate(x, p);
}
}
if (To == ) rt = x;
} int find(int key)
{
int x = rt;
while (x && T[x].key != key)
x = T[x].son[key > T[x].key];
if (x) Splay(x, );
return x;
} int prev()
{
int x = T[rt].son[];
if (!x) return ;
while (T[x].son[])
x = T[x].son[];
//Splay(x, 0);
return x;
} int succ()
{
int x = T[rt].son[];
if (!x) return ;
while (T[x].son[])
x = T[x].son[];
//Splay(x, 0);
return x;
} void Insert(int key)
{
if (!rt)
T[rt = cnt++].set(key, , );
else
{
int x = rt, y = ;
while (x)
{
y = x;
x = T[x].son[key > T[x].key];
}
T[x = cnt++].set(key, , y);
T[y].son[key > T[y].key] = x;
Splay(x, );
}
} void Delete(int key)
{
int x = find(key);
if (!x) return;
int y = T[x].son[];
while (T[y].son[])
y = T[y].son[];
int z = T[x].son[];
while (T[z].son[])
z = T[z].son[];
if (!y && !z)
{
rt = ;
return;
}
if (!y)
{
Splay(z, );
T[z].son[] = ;
PushUp(z);
return;
}
if (!z)
{
Splay(y, );
T[y].son[] = ;
PushUp(y);
return;
}
Splay(y, );
Splay(z, y);
T[z].son[] = ;
PushUp(z);
PushUp(y);
} int GetPth(int p)
{
if (!rt) return ;
int x = rt, ret = ;
while (x)
{
if (p == T[T[x].son[]].size + )
break;
if (p>T[T[x].son[]].size + )
{
p -= T[T[x].son[]].size + ;
x = T[x].son[];
}
else
x = T[x].son[];
}
Splay(x, );
return x;
} int GetRank(int key)
{
if (!rt) return ;
int x = rt, ret = , y;
while (x)
{
y = x;
if (T[x].key <= key)
{
ret += T[T[x].son[]].size + ;
x = T[x].son[];
}
else
x = T[x].son[];
}
Splay(y, );
return ret;
}
int main(){
//#ifdef kirito
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
//#endif
// int start = clock();
int n;
while (~scanf("%d", &n)){
LL ans = ; rt = ; cnt = ; T[].set(INF, , );
for (int i = ; i <= n; i++){
int val; scanf("%d", &val);
Insert(val);
if (i == ){ ans = val; }
else{
ans += min(abs(val - T[succ()].key), abs(val - T[prev()].key));
}
}
printf("%lld\n", ans);
}
//#ifdef LOCAL_TIME
// cout << "[Finished in " << clock() - start << " ms]" << endl;
//#endif
return ;
}

HYSBZ 1588 营业额统计的更多相关文章

  1. HYSBZ - 1588 营业额统计 (伸展树)

    题意:营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额.分析营 ...

  2. HYSBZ 1588 营业额统计 (Splay树)

    题意:给出一个公司每一天的营业额,求每天的最小波动值之和.该天的最小波动值= min { 绝对值| 该天以前某一天的营业额-该天的营业额 | }.第一天的最小波动值就是其自己. 思路:Splay伸展树 ...

  3. (HYSBZ)BZOJ 1588 营业额统计

    营业额统计 Time Limit: 5000MS   Memory Limit: 165888KB   64bit IO Format: %lld & %llu Description 营业额 ...

  4. BZOJ 1588 营业额统计

    Description 营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来每 ...

  5. BZOJ 1588 营业额统计 set

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1588 题目大意: 营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交 ...

  6. bzoj 1588营业额统计(HNOI 2002)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1588 splay  bottom-up的数组实现. 题意就是给你一组数,求每个数与在其前面且与其最相 ...

  7. BZOJ 1588 营业额统计 Splay

    主要操作为Splay中插入节点,查找前驱和后继节点. 1: #include <cstdio> 2: #include <iostream> 3: #include <c ...

  8. [bzoj] 1588 营业额统计 || Splay板子题

    原题 给出一个n个数的数列ai ,对于第i个元素ai定义\(fi=min(|ai-aj|) (1<=j<i)\),f1=a1,求\(/sumfi\) Splay板子题. Splay讲解:h ...

  9. 营业额统计 HYSBZ - 1588

    营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额.分析营业情况 ...

随机推荐

  1. Android 运行时权限处理

    引言 Android 6.0 (API 23) 开始引入了运行时权限检查 (Permissions at Run Time),用户不需要在安装时同意授予应用权限,而是在应用运行时动态去申请所需要的权限 ...

  2. 【leetcode】Gray Code (middle)

    The gray code is a binary numeral system where two successive values differ in only one bit. Given a ...

  3. codeforces gym 100286 I iSharp (字符串模拟)

    题目链接 给定一个字符串.输入是int& a*[]&, b, c*; 输出是 int&&[]* a;int& b;int&* c; 输入格式里逗号后面一 ...

  4. 修改VS2010生成的dll文件中的内容

    我的电脑是64为的操作系统,所以先找到下面的路径 C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin 找到这个文件:ildasm.exe,如 ...

  5. .NET微信公众号开发-3.0查询自定义菜单

    一.前言 前面我们已经创建好了我们的自定义菜单.那么我们现在要如何查询我们自定义的菜单.原理都是一样的,而且都是相当简单,只是接口地址文档换掉了. 2.0开始编码 同样我们首先创建好我的查询页面,在这 ...

  6. sqlserver 数据库中时间函数的建立

    create function [dbo].[HtoSec](@lvalue as int)RETURNS intBEGINDECLARE @temp intSet @temp = @lvalue * ...

  7. Redis自定义动态字符串(sds)模块(二)

    sds模块的具体实现: 1.sdsnewlen 根据参数生成一个sds字符串 sds sdsnewlen(const void *init, size_t initlen) { struct sdsh ...

  8. PHP中 字符串 常用函数

    //strpos    查找字符串中是否含有字符 $str='abcde'; $char='a':   if(strpos($str,$char) !==false){    echo '含有',$c ...

  9. Python中如何读取xls中的数据

    要想读取EXCEL中的数据,首先得下载xlrd包,地址:https://pypi.python.org/pypi/xlrd  安装方法:下载解压后,利用windows  dos命令进入解压目录eg,c ...

  10. Jquery学习笔记---闭包

    1. 简要介绍 闭包可谓是js中的一大特色了,即使你对闭包没概念,你可能已经在不知不觉中使用到了闭包.闭包是什么,闭包就是一个函数可以访问到另一个函数的变量.这就是闭包,解释起来就这么一句话,不明白? ...