题意:给定一个序列,求另一个不递减序列,使得Abs(bi - ai) 和最小。

析:首先是在每个相同的区间中,中位数是最优的,然后由于要合并,和维护中位数,所以我们选用左偏树来维护,当然也可以用划分树来做。

代码如下:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#include <sstream>
#define debug() puts("++++");
#define gcd(a, b) __gcd(a, b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define freopenr freopen("in.txt", "r", stdin)
#define freopenw freopen("out.txt", "w", stdout)
using namespace std; typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const double inf = 0x3f3f3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 50000 + 10;
const int mod = 1e6 + 10;
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};
const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline int Abs(int x){ return x > 0 ? x : -x; }
inline bool is_in(int r, int c){
return r >= 0 && r < n && c >= 0 && c < m;
}
struct Node{ int key, l, r, d, fa; };
Node tr[maxn];
int iroot(int i){
if(i == -1) return -1;
while(tr[i].fa != -1) i = tr[i].fa;
return i;
} int Merge(int rx, int ry){
if(rx == -1) return ry;
if(ry == -1) return rx;
if(tr[rx].key < tr[ry].key) swap(rx, ry);
int r = Merge(tr[rx].r, ry);
tr[rx].r = r; tr[r].fa = rx;
if(tr[tr[rx].l].d < tr[r].d) swap(tr[rx].l, tr[rx].r);
if(tr[rx].r == -1) tr[rx].d = 0;
else tr[rx].d = tr[tr[rx].r].d + 1;
return rx;
} int del(int i){
if(i == -1) return -1;
int l = tr[i].l, r = tr[i].r, y = tr[i].fa, x;
tr[i].l = tr[i].r = tr[i].fa = -1;
tr[x = Merge(l, r)].fa = y;
if(y != -1 && tr[y].l == i) tr[y].l = x;
else if(y != -1 && tr[y].r == i) tr[y].r = x;
for( ; y != -1; x = y, y = tr[y].fa){
if(tr[tr[y].l].d < tr[tr[y].r].d) swap(tr[y].l, tr[y].r);
if(tr[y].d == tr[tr[y].r].d + 1) break;
tr[y].d = tr[tr[y].r].d + 1;
}
if(x != -1) return iroot(x);
return iroot(y);
} int top(int i){ return tr[i].key; }
int pop(int &i){
Node out = tr[i];
int l = tr[i].l, r = tr[i].r;
tr[i].l = tr[i].r = tr[i].fa = -1;
tr[l].fa = tr[r].fa = -1;
i = Merge(l, r);
return out.key;
} int a[maxn];
void init(){
for(int i = 0; i < n; ++i){
scanf("%d", a+i);
tr[i].key = a[i];
tr[i].l = tr[i].r = tr[i].fa = -1;
tr[i].d = 0;
}
}
int tree[maxn], sz[maxn], cnt[maxn]; void solve(){
int m = -1;
for(int i = 0; i < n; ++i){
tree[++m] = i;
sz[m] = cnt[m] = 1;
while(m > 0 && top(tree[m-1]) >= top(tree[m])){
tree[m-1] = Merge(tree[m-1], tree[m]);
sz[m-1] += sz[m];
cnt[m-1] += cnt[m];
--m;
while(cnt[m] > (sz[m]+1) / 2){
pop(tree[m]);
--cnt[m];
}
}
}
LL ans = 0;
int k = 0;
for(int i = 0; i <= m; ++i){
int t = top(tree[i]);
for(int j = 0; j < sz[i]; ++j, ++k)
ans += Abs(t - a[k]);
}
printf("%lld\n", ans);
} int main(){
while(scanf("%d", &n) == 1 && n){
init();
solve();
}
return 0;
}

  

ZOJ 3512 Financial Fraud (左偏树)的更多相关文章

  1. zoj 2334 Monkey King/左偏树+并查集

    原题链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1389 大致题意:N只相互不认识的猴子(每只猴子有一个战斗力值) 两只 ...

  2. 左偏树(Leftist Heap/Tree)简介及代码

    左偏树是一种常用的优先队列(堆)结构.与二叉堆相比,左偏树可以高效的实现两个堆的合并操作. 左偏树实现方便,编程复杂度低,而且有着不俗的效率表现. 它的一个常见应用就是与并查集结合使用.利用并查集确定 ...

  3. BZOJ 1455 罗马游戏 ——左偏树

    [题目分析] 左偏树的模板题目,大概就是尽量维护树的深度保持平衡,以及尽可能的快速合并的一种堆. 感觉和启发式合并基本相同. 其实并没有快很多. 本人的左偏树代码自带大常数,借鉴请慎重 [代码] #i ...

  4. 【BZOJ-1455】罗马游戏 可并堆 (左偏树)

    1455: 罗马游戏 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1355  Solved: 561[Submit][Status][Discuss] ...

  5. 【bzoj2809】[Apio2012]dispatching 左偏树

    2016-05-31  15:56:57 题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2809 直观的思想是当领导力确定时,尽量选择薪水少的- ...

  6. POJ3016-K-Monotonic(左偏树+DP)

    我觉得我要改一下签名了……怎么会有窝这么啰嗦的人呢? 做这题需要先学习左偏树<左偏树的特点及其应用> 然后做一下POJ3666,这题的简单版. 思路: 考虑一下维护中位数的过程原数组为A, ...

  7. POJ3666-Making the Grade(左偏树 or DP)

    左偏树 炒鸡棒的论文<左偏树的特点及其应用> 虽然题目要求比论文多了一个条件,但是……只需要求非递减就可以AC……数据好弱…… 虽然还没想明白为什么,但是应该觉得应该是这样——求非递减用大 ...

  8. bzoj 1455: 罗马游戏 左偏树+并查集

    1455: 罗马游戏 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 668  Solved: 247[Submit][Status] Descriptio ...

  9. 黄源河《左偏树的应用》——数字序列(Baltic 2004)

    这道题哪里都找不到. [问题描述] 给定一个整数序列a1, a2, … , an,求一个不下降序列b1 ≤ b2 ≤ … ≤ bn,使得数列{ai}和{bi}的各项之差的绝对值之和 |a1 - b1| ...

随机推荐

  1. EasyPlayer RTSP 安卓Android播放器显示模式设置方法

    一般对于一个播放器,应该支持如下几种显示模式: 等比例,最大化区域显示,不裁剪 等比例,最大区域显示,裁剪 拉伸显示,铺满全屏 要实现这几种显示模式,其实只要对播放控件的布局进行些许调整即可.那Eas ...

  2. iOS App打包上架超详细流程

    https://www.jianshu.com/p/817686897ec1?open_source=weibo_search

  3. js为Object对象动态添加属性和值 eval c.k c[k]

    const appendInfo = () => { const API_SECRET_KEY = 'https://github.com/dyq086/wepy-mall/tree/maste ...

  4. php计算数组的维数

    function array_dim($arr){ if(!is_array($arr)) return 0; else{ $max1 = 0; foreach($arr as $item1){ $t ...

  5. Linux系统中的python2.x升级至python3

    python2.x升级至python3 由于需要在公司测试环境搭建的Jenkins上面运行接口自动化脚本,所以需要对Jenkins所处的服务器的python环境进行升级,以便运行python3编写的脚 ...

  6. typescript import 全局node_modules报错

    项目里面有一个node_modules的包太大,每次放到docker里面都要下载半天,大大减少了部署效率. 所以考虑将这个node包全局安装到docker的基础镜像中,那么代码里面直接引用全局包就可以 ...

  7. 我的Java开发学习之旅------>Java经典排序算法之选择排序

    一.算法原理 对比数组中前一个元素跟后一个元素的大小,如果后面的元素比前面的元素小则用一个变量k来记住他的位置, 接着第二次比较,前面"后一个元素"现变成了"前一个元素& ...

  8. 20145239 杜文超 实验四 Android开发基础

    20145239实验四 Android开发基础 实验内容 基于Android Studio开发简单的Android应用并部署测试 了解Android组件.布局管理器的使用 掌握Android中事件处理 ...

  9. C++中输出 位宽和小数点后位数 的控制

    要用到这个头文件: <iomanip> setw(x) : 表示控制输出x的位宽 setprecision(x) :表示 控制输出小数点后 x 位 cout.precision(x): 表 ...

  10. R语言快捷键

    一.控制台 功能  Windows & Linux   Mac 移动鼠标到控制台 Ctrl+2 Ctrl+2 移动到鼠标命令编辑 Ctrl+1 Ctrl+1 控制台清屏 Ctrl+L Comm ...