zoukankan      html  css  js  c++  java
  • luogu 3466 对顶堆

    显然答案是将一段区间全部转化成了其中位数
    这样的话,需要维护一个数据结构支持查询当前所有数中位数
    对顶堆
    用两个堆
    将 < 中位数的数放入大根堆
    将 > 中位数的数放入小根堆
    这样就会存在删除操作
    删除的时候
    由于无法快速删除
    只需做个标记,标记该数被删除了一次
    并且堆的实际大小也应该另外记录维护
    在标记时需要更改相应的堆的大小与权值
    答案就非常显然了

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define gc getchar()
    inline int read() {
        int x = 0; char c = gc;
        while(c < '0' || c > '9') c = gc;
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc;
        return x;
    }
    
    #define Rep(i, a, b) for(int i = a; i <= b; i ++)
    #define Fin(str) freopen(str, "r", stdin)
    #define Fout(str) freopen(str, "w", stdout)
    #define E return
    #define LL long long
    
    const int N = 1e5 + 10;
    
    int n, k;
    int A[N], use[N * 10];
    
    priority_queue <int, vector<int>, less<int> > Big;
    priority_queue <int, vector<int>, greater<int> > Small;
    
    int Size1, Size2;
    LL Sum1, Sum2;
    
    void Update() {
        while(Big.size() && use[Big.top()]) use[Big.top()] --, Big.pop();
        while(Small.size() && use[Small.top()]) use[Small.top()] --, Small.pop();
    }
    
    void Out();
    
    void Add(int x) {
        Update();
        while(Size1 < (k + 1) / 2 && Small.size()) {
            int num = Small.top();
            Small.pop();
            Size1 ++, Sum1 += num;
            Size2 --, Sum2 -= num;
            Big.push(num);
            Update();
        }
        Update();
        if(Size1 < (k + 1) / 2) {
            Size1 ++, Sum1 += x, Big.push(x); return ;
        }
        Update();
        int num = Big.top();
        if(x < num) {
            Small.push(num);
            Big.pop();
            Size2 ++, Sum2 += num;
            Sum1 += (x - num);
            Big.push(x);
        } else {
            Size2 ++, Sum2 += x, Small.push(x); 
        }
        Update();
    }
    
    void Del(int x) {
        use[x] ++;
        int top1 = Big.top();
        if(x <= top1) Size1 --, Sum1 -= x;
        else Size2 --, Sum2 -= x;
    }
    
    LL Calc() {
        Update();
        LL mid = Big.top();
        return 1ll * mid * Size1 - 1ll * Sum1 + 1ll * Sum2 - 1ll * mid * Size2;
    }
    
    int main() {
        n = read(), k = read();
        Rep(i, 1, n) A[i] = read();
        Rep(i, 1, k) Add(A[i]);
        LL Answer = Calc();
        int bef = 0;
        int flag = k, mid = Big.top();
        Rep(i, k + 1, n) {
            Del(A[++ bef]);
            Add(A[i]);
            LL Ans = Calc();
            if(Ans < Answer) {
                flag = i, mid = Big.top();
                Answer = Ans;
            }
        }
        cout << Answer << "
    ";
        Rep(i, 1, n) {
            if(i <= flag && i >= flag - k + 1) {
                cout << mid << "
    ";
            } else cout << A[i] << "
    ";
        }
        return 0;
    }
  • 相关阅读:
    如何在Ubuntu 18.04上安装Memcached
    ubuntu安装mysql添加密码
    Django学习---快速搭建搜索引擎(haystack + whoosh + jieba)
    django3.x 使用haystack 报错:ImportError: cannot import name 'six' from 'django.utils'
    spring boot2之Jackson和ObjectMapper
    python之装饰器强制函数上的类型检查
    python之*args和**kwargs的区别
    Python之@property
    python基础语法之and,or,not
    小案例
  • 原文地址:https://www.cnblogs.com/shandongs1/p/9762963.html
Copyright © 2011-2022 走看看