题目链接: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. RSA 加解密转换

    由于项目的原因,原来的项目使用.net 进行开发,现在需要转成java, 所以原来的加解密就成了一个棘手的问题.由于数据使用RSA签名加密,又因为.net 和 Java 加解密算法上的差异,并不能使用 ...

  2. 最牛逼android上的图表库MpChart(二) 折线图

    最牛逼android上的图表库MpChart二 折线图 MpChart折线图介绍 MpChart折线图实例 MpChart效果 最牛逼android上的图表库MpChart(二) 折线图 最近工作中, ...

  3. Google推荐的图片加载库Glide介绍

    英文原文 Introduction to Glide, Image Loader Library for Android, recommended by Google 译文首发  http://jco ...

  4. HDU 5762 Teacher Bo (鸽笼原理) 2016杭电多校联合第三场

    题目:传送门. 题意:平面上有n个点,问是否存在四个点 (A,B,C,D)(A<B,C<D,A≠CorB≠D)使得AB的横纵坐标差的绝对值的和等于CD的横纵坐标差的绝对值的和,n<1 ...

  5. 多米诺(codevs 3052)

    题目描述 Description 一个矩形可以划分成M*N个小正方形,其中有一些小正方形不能使用.一个多米诺骨牌占用两个相邻的小正方形.试问整个区域内最多可以不重叠地放多少个多米诺骨牌且不占用任何一个 ...

  6. DOM对象与JQUERY对象的相互转化

    普通处理,通过标准JavaScript处理: 1 var p = document.getElementById('imooc') 2 p.innerHTML = '您好!学习jQuery才是最佳的途 ...

  7. js递归

    先从外层往里调,再反. 要想明白,必须明白执行过程. 如果再不理解,就看函数功能.   函数里自己调自己就是递归!

  8. 在MVC的项目中访问静态页面

    MVC在生成项目的时候会生成的WEB-INF底下.这个文件夹下面的文件是受保护的,都会走MVC的流程, 但是我希望在WebContent底下可以使用静态页面, 那么需要进入springmvc-serv ...

  9. ViewPager部分源码分析二:FragmentManager对Fragment状态的管理完成ViewPager的child添加或移出

    ViewPager维护child代码流程: 注:PagerAdapter 使用的是FragmentPagerAdapter类或者它的子类. viewPager.populate(): void pop ...

  10. Android中Service 使用详解(LocalService + RemoteService)

    Service 简介: Service分为本地服务(LocalService)和远程服务(RemoteService): 1.本地服务依附在主进程上而不是独立的进程,这样在一定程度上节约了资源,另外L ...