HYSBZ 1588 营业额统计
题目链接: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 营业额统计的更多相关文章
- HYSBZ - 1588 营业额统计 (伸展树)
题意:营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额.分析营 ...
- HYSBZ 1588 营业额统计 (Splay树)
题意:给出一个公司每一天的营业额,求每天的最小波动值之和.该天的最小波动值= min { 绝对值| 该天以前某一天的营业额-该天的营业额 | }.第一天的最小波动值就是其自己. 思路:Splay伸展树 ...
- (HYSBZ)BZOJ 1588 营业额统计
营业额统计 Time Limit: 5000MS Memory Limit: 165888KB 64bit IO Format: %lld & %llu Description 营业额 ...
- 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拿出了公司的账本,账本上记录了公司成立以来每天的营业额.分析营业情况 ...
随机推荐
- windows编程注意点(持续更新)
1.windows编程中,所有的操作都放到窗口过程中进行,main函数只用于描述窗口基本信息. 2.用于获取设备环境句柄时,用BeginPaint/EndPaint,消耗cpu小,但占内存大;用Get ...
- 为什么使用<!DOCTYPE HTML>
不管是刚接触前端,还是你已经"精通"web前端开发的内容,你应该知道在你写html的时候需要定义文档类型:你知道如果没有它,浏览器在渲染页面的时候会使用怪异模式:你知道各个浏览器在 ...
- sql server 导出表结构
今天准备整理下手里面几个数据库,形成一个表结构文档,方便以后维护使用. 网上找到一个脚本还不错,小小的修改就满足了我的要求,执行完SQL脚本. 在结果就能看到数据库所有表的结构,这个时候只要全选,然后 ...
- 【QT】C++ GUI Qt4 学习笔记4
感觉这本书的顺序设计的太不合理了,出现的最多的一句话就是后面会讲.按照使用的顺序讲不行吗?搞得代码都运行不了. 我决定先直接跳到73页,子类化QTableWidgetItem这一节.因为前面功能的实现 ...
- swift枚举
以下是指南针四个方向的一个例子: enum CompassPoint { case North case South case East case West } 多个成员值可以出现在同一行上,用 ...
- Mysql之复制选项与监控
1.Slave 筛选选项: --replicate-do-db ,同步复制哪些库 --replicate-ignore-db,忽略哪些库 --replicate-do-table=db_name.t ...
- ld returned 1 exit status"的解决办法
在Linux下创建线程时,编译时会出现下面的错误,[root@linuxserver 807]# gcc -o 22 22.c/tmp/cc21HcoW.o(.text+0x4c): In funct ...
- Java使用正则表达式解析LRC歌词文件
LRC歌词是一种应用广泛的歌词文件,各主流播放器都支持. lrc歌词文本中含有两类标签: 1.标识标签(ID-tags) [ar:艺人名] [ti:曲名] [al:专辑名] [by:编者(指编辑LRC ...
- Linux下第一次使用MySQL数据库,设置密码
在终端下输入:/etc/rc.d/init.d/mysqld status 查看MySQL状态,看看是否运行. 没有运行的话就输入:/etc/rc.d/init.d/mysqld start 这时,就 ...
- 二、JavaScript语言--JS实践--信息滚动效果制作
运用JavaScript技术,掌握无缝滚动和歇间性滚动的制作方法. 一.marquee标签实现信息滚动 1 behavior滚动的方式 alternate:表示在两端之间来回滚动 scroll:表示由 ...