zoukankan      html  css  js  c++  java
  • 【堆】B001_分级(大/小根堆分别维护升/降序序列)

    给定长度为N的序列A,构造一个长度为N的序列B,满足:

    1. B非严格单调,即B1≤B2≤…≤BN或B1≥B2≥…≥BN。
    2. 最小化 S=∑Ni=1|Ai−Bi|。
      只需要求出这个最小值S。

    输入格式
    第一行包含一个整数N。
    接下来N行,每行包含一个整数Ai。
    输出格式
    输出一个整数,表示最小S值。
    数据范围
    1≤N≤2000,
    0≤Ai≤109

    输入样例:
    7
    1
    3
    2
    4
    5
    3
    9
    输出样例:
    3
    

    方法一:大小根堆

    用小根堆维护一个降序的序列B和用大根堆维护一个升序的序列B,具体为:

    • 当维护一个升序序列时,当后面遍历到的元素x比大根堆maxQ的堆顶元素还要小的话,那就要对x做出调整,增量为 maxQ.top()-x
    • 当维护一个降序序列时,当后面遍历到的元素x比小根堆minQ的堆顶元素还要大的话,那也要对x做出调整,减量为 x-minQ.top()
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    int main() {
        std::ios::sync_with_stdio(false);
        cin.tie(0);cout.tie(0);
        ll n, ans1=0, ans2=0; cin>>n;
        int A[n]; for (int i=0; i<n; i++) cin>>A[i];
        priority_queue<ll> maxQ;
        priority_queue<ll, vector<ll>, greater<int>> minQ;
    
        for (ll x : A) {      //维护升序序列
            maxQ.push(x);
            if (x<maxQ.top()) {
                ans1+=maxQ.top()-x; 
                maxQ.pop(), maxQ.push(x);
            }
        }
        for (ll x : A) {      //维护降序序列
            minQ.push(x);
            if (x>minQ.top()) {
                ans2+=x-minQ.top(); 
                minQ.pop(), minQ.push(x);
            }
        }
        cout << min(ans1, ans2);
        return 0;
    }
    

    复杂度分析

    • Time\(O(nlogn)\)
    • Space\(O(n)\)
  • 相关阅读:
    个人技术博客(α)
    git常用命令合集
    软件工程实践2017第二次结对作业
    软件工程实践2017第一次结对作业
    软件工程实践2017第二次作业
    软件工程实践2017第一次作业
    学习总结
    约瑟夫
    今天是星期几
    斐波那契数列取石子游戏
  • 原文地址:https://www.cnblogs.com/wdt1/p/13630457.html
Copyright © 2011-2022 走看看