• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
dwtfukgv
博客园    首页    新随笔    联系   管理    订阅  订阅
左偏树
#include <stdio.h>  
#include <iostream>  
using namespace std;  
  
#define typec int       // type of key val  
#define N 50005  
  
int zabs(int x) {  
    if (x < 0) return -x;  
    else return x;  
}  
  
const int na = -1;  
struct node { typec key; int l, r, f, dist; } tr[N];  
  
int ary[N];  
int tree[N], size[N], cunt[N];  
  
// 获得结点i的根  
int iroot(int i) {  
    if (i == na) return i;  
    while (tr[i].f != na) i = tr[i].f;  
    return i;  
}  
  
// 合并两棵左偏树, param: rx ry (two root)  
int merge(int rx, int ry) {       
    if (rx == na) return ry;  
    if (ry == na) 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].f = rx;  
    if (tr[r].dist > tr[tr[rx].l].dist) swap(tr[rx].l, tr[rx].r);  
    if (tr[rx].r == na) tr[rx].dist = 0;  
    else tr[rx].dist = tr[tr[rx].r].dist + 1;  
    return rx;                          // return new root  
}  
  
// 插入一个新节点  
int ins(int i, typec key, int root) {  
    tr[i].key = key;  
    tr[i].l = tr[i].r = tr[i].f = na;  
    tr[i].dist = 0;  
    return root = merge(root, i);       // return new root  
}  
  
// 删除某个结点  
int del(int i) {  
    if (i == na) return i;  
    int x, y, l, r;  
    l = tr[i].l; r = tr[i].r; y = tr[i].f;  
    tr[i].l = tr[i].r = tr[i].f = na;  
    tr[x = merge(l, r)].f = y;  
    if (y != na && tr[y].l == i) tr[y].l = x;  
    if (y != na && tr[y].r == i) tr[y].r = x;  
    for ( ; y != na; x = y, y = tr[y].f) {  
        if (tr[tr[y].l].dist < tr[tr[y].r].dist)  
            swap(tr[y].l, tr[y].r);  
        if (tr[tr[y].r].dist + 1 == tr[y].dist) break;  
        tr[y].dist = tr[tr[y].r].dist + 1;  
    }  
    if (x != na) return iroot(x);       // return new root  
    else return iroot(y);  
}  
  
// 获取最小结点  
node top(int root) {  
    return tr[root];  
}  
  
// 取得并删除最小结点  
node pop(int &root) {  
    node out = tr[root];  
    int l = tr[root].l, r = tr[root].r;  
    tr[root].l = tr[root].r = tr[root].f = na;  
    tr[l].f = tr[r].f = na;  
    root = merge(l, r);  
    return out;  
}  
  
// 增/减一个结点的键值  
int add(int i, typec val) {  
    if (i == na) return i;  
    if (tr[i].l == na && tr[i].r == na && tr[i].f == na) {  
        tr[i].key += val;  
        return i;  
    }  
    typec key = tr[i].key + val;  
    int rt = del(i);  
    return ins(i, key, rt);  
}  
  
// 初始化数据  
void init(int n) {  
    for (int i = 0; i < n; i++) {  
        scanf("%d", &ary[i]);  
        tr[i].key = ary[i];  
        tr[i].l = tr[i].r = tr[i].f = na;  
        tr[i].dist = 0;  
    }  
}  
  
void solve(int n) {  
    int m = -1;  
    for (int i = 0; i < n; i++) {  
        tree[++m] = i;  
        size[m] = 1;  
        cunt[m] = 1;  
        while (m > 0 && top(tree[m]).key <= top(tree[m-1]).key) {  
            tree[m-1] = merge(tree[m], tree[m-1]);  
            size[m-1] += size[m];  
            cunt[m-1] += cunt[m];  
            m--;  
            while (cunt[m] > (size[m] + 1) / 2) {  
                pop(tree[m]);  
                cunt[m]--;  
            }  
        }  
    }  
  
    int k = 0;  
    long long res = 0;  
    for (int i = 0; i <= m; i++) {  
        int v = top(tree[i]).key;  
        for (int j = 0; j < size[i]; j++) {  
            res += zabs(ary[k++] - v);  
        }  
    }  
    printf("%lld\n", res);  
}  
  
int main() {  
    int n;  
    while (scanf("%d", &n), n) {  
        init(n);  
        solve(n);  
    }  
    return 0;  
}  

  

struct node { typec key; int l, r, f, dist; } tr[N];

1.   // 获得结点i的根  

2.   int iroot(int i) {  

3.       if (i == na) return i;  

4.       while (tr[i].f != na) i = tr[i].f;  

5.       return i;  

6.   }  

7.   // 合并两棵左偏树, param: rx ry (two root)  

8.   int merge(int rx, int ry) {       

9.       if (rx == na) return ry;  

10.    if (ry == na) return rx;  

11.    if (tr[rx].key < tr[ry].key) swap(rx, ry);  

12.    int r = merge(tr[rx].r, ry);  

posted on 2017-03-31 18:22  dwtfukgv  阅读(118)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3