• bzoj1367


    可并堆

    对于一段递减的序列我们可以取中位数作为b

    那么我们可以把a分成几段递减的序列,每段都取中位数,并且中位数递增

    那么维护一个单调栈,每次新加入元素,如果当前段的中位数比之前小就吃掉之前的

    中位数用可并堆维护,维护前n/2大的数就行了

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define abs(x) x < 0 ? -x : x
    using namespace std;
    const int M = 1e6 + 6;
    int n, top;
    struct node {
        int lc, rc, d, k;
    } t[M];
    int a[M], half[M], root[M], st[M], sz[M], cnt[M], l[M], r[M];
    int _abs(int x) {
        return x < 0 ? -x : x;
    }
    int Merge(int u, int v) {
        if(!u || !v) {
            return u + v;
        }
        if(t[u].k < t[v].k) {
            swap(u, v);
        }
        t[u].rc = Merge(t[u].rc, v);
        if(t[t[u].rc].d > t[t[u].lc].d) {
            swap(t[u].lc, t[u].rc);
        }
        if(!t[u].rc) {
            t[u].d = 0;
        } else {
            t[u].d = t[t[u].rc].d + 1;
        }
        return u;
    }
    int Top(int x) {
        return t[x].k;
    }
    int Pop(int x) {
        return Merge(t[x].lc, t[x].rc);
    }
    int main() {
        scanf("%d", &n);
        for(int i = 1; i <= n; ++i) {
            scanf("%d", &a[i]);
            a[i] -= i;
        }
        for(int i = 1; i <= n; ++i) {
            root[i] = i;
            sz[i] = 1;
            half[i] = 1;
            l[i] = r[i] = i;
            t[i].k = a[i];
            while(top && Top(root[st[top]]) > Top(root[i])) {
                root[i] = Merge(root[st[top]], root[i]);
                sz[i] = sz[i] + sz[st[top]];
                half[i] = half[i] + half[st[top]];
                while(half[i] * 2 > sz[i] + 1) {
                    root[i] = Pop(root[i]);
                    --half[i];
                }
                l[i] = l[st[top]];
                --top;
            }
            st[++top] = i;
        }
        long long ans = 0;
        for(int i = 1; i <= top; ++i) {
            for(int j = l[st[i]]; j <= r[st[i]]; ++j) {
                ans += _abs(a[j] - Top(root[st[i]]));
            }
        }
        printf("%lld
    ", ans);
        return 0;
    }
    View Code
  • 相关阅读:
    C#中子线程操作主线程中窗体上控件的方法
    关于VS2010在使用过程中的一些便捷之处
    WCF 开发日志 WCF契约设计
    OEA框架学习:运行时
    OEA框架学习:使用动软代码生成器
    OEA框架学习:多线程
    批处理定时自动更新SVN
    读书笔记:高效经理人的8个思维原则
    C# WinForm 技巧五:WinForm界面生成
    WCF开发日志 OEA里面的WCF设计
  • 原文地址:https://www.cnblogs.com/19992147orz/p/8507224.html
Copyright © 2020-2023  润新知