• [堆]JZOJ 1208 车展


    Description

    遥控车是在是太漂亮了,韵韵的好朋友都想来参观,所以游乐园决定举办m次车展。车库里共有n辆车,从左到右依次编号为1,2,…,n,每辆车都有一个展台。刚开始每个展台都有一个唯一的高度h[i]。主管已经列好一张单子:
    L1 R1
    L2 R2

    Lm Rm
    单子上的(Li,Ri)表示第i次车展将要展出编号从Li到Ri的车。
    为了更加美观,展览时需要调整展台的高度,使参展所有展台的高度相等。展台的高度增加或减少1都需花费1秒时间。由于管理员只有一个人,所以只好对每个展台依次操作。每次展览结束后,展台高度自动恢复到初始高度。
    请告诉管理员为了举办所有展览,他最少需要花多少时间将展台调整好。
     

    Input

    第一行为两个正整数n、m。
    第二行共n个非负整数,表示第i辆车展台的高度h[i]。
    接下来m行每行2个整数Li、Ri(Li≤Ri)。

    Output

    一个正整数,调整展台总用时的最小值。
     

    Sample Input

    6 4
    4 1 2 13 0 9
    1 5
    2 6
    3 4
    2 2
    

    Sample Output

    48
     

    Data Constraint

     
     

    Hint

    【数据规模和约定】
    对于50%的数据 n≤500,m≤1000;
    对于80%的数据 n≤1000,m≤100000;
    对于100%的数据n≤1000,m≤200000;
    答案小于2^64。

    分析

    显然我们以中位数为目标最佳(我赛场打了splay???(干什么不打Treap))

    那么用传统的双堆法求中位数即可

    #include <iostream>
    #include <cstdio>
    #include <queue>
    using namespace std;
    typedef long long ll;
    const int N=1010;
    priority_queue<ll> b;
    priority_queue<ll,vector<ll>,greater<ll> > a;
    ll ans[N][N],h[N],suma,sumb,cnta,cntb;
    int n,m;
    
    int main() {
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++) scanf("%lld",&h[i]);
        for (int i=1;i<=n;i++) {
                while (!a.empty()) a.pop();
                while (!b.empty()) b.pop();
                suma=sumb=cnta=cntb=0;
                a.push(h[i]);cnta=1;suma+=h[i];
                for (int j=i+1;j<=n;j++) {
                    if (cnta==cntb) {
                        if (h[j]>=b.top()) a.push(h[j]),cnta++,suma+=h[j];
                        else {
                            ll x=b.top();
                            b.pop();sumb-=x;a.push(x);suma+=x;cnta++;b.push(h[j]);sumb+=h[j];
                        }
                    }
                    else
                        if (h[j]<=a.top()) b.push(h[j]),cntb++,sumb+=h[j];
                        else {
                            ll x=a.top();
                            a.pop();suma-=x;b.push(x);sumb+=x;cntb++;a.push(h[j]);suma+=h[j];
                        }
                    ans[i][j]=suma-cnta*a.top()+a.top()*cntb-sumb;
                }
        }
        ll lans=0;
        for (int i=1;i<=m;i++) {
            int x,y;
            scanf("%d%d",&x,&y);
            lans+=ans[x][y];
        }
        printf("%lld
    ",lans);
    }
    View Code
    在日渐沉没的世界里,我发现了你。
  • 相关阅读:
    8.1 管道符| 使用技巧
    7.1 elementui的radio无法选中问题
    2.0 es6数组操作
    小练习-双数日期
    匿名函数、三元表达式、列表生成式
    sys.argv
    常用模块 os,sys,
    Python操作数据库
    Python time模块
    加密模块hashlib
  • 原文地址:https://www.cnblogs.com/mastervan/p/9699169.html
Copyright © 2020-2023  润新知