newcoder61132L <multiset 维护中位数>

发布时间 2023-07-12 19:38:19作者: O2iginal

题目

中位数
多次询问,每次修改数组中一个数,问修改后n个数的中位数

思路

  • 使用multiset,分别维护数组的较大的\(n/2+1\)个和较小的\(n/2\)个;
  • 根据数据范围,或许可用线段树+二分...

代码

Code

#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
#include <set>
using namespace std;
using LL = long long;
const int N = 1e6 + 10;
int a[N];
int b[N];

void print(multiset<int> &a)
{
    for (auto it: a) cout << it << ' ';
    cout << endl;
}
void solv()
{
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i ++) 
    {
        cin >> a[i];
        b[i] = a[i];
    }
    sort(b+1, b+1+n);
    multiset<int> big, small;
    int mid = n/2 + 1;
    for (int i = 1; i < mid; i ++) small.insert(b[i]);
    for (int i = mid; i <= n; i ++) big.insert(b[i]);    // mid -> big.begin

    int p, x;
    for (int i = 1; i <= m; i ++)
    {
        // cout << "i = " << i << endl;
        cin >> p >> x;
        auto pos = small.find(a[p]);
        if (pos != small.end()) small.erase(pos);
        else big.erase(big.find(a[p]));
        big.insert(x); a[p] = x;

        while (big.size() > small.size() + 1)
        {
            auto pos1 = big.begin();
            small.insert(*pos1);
            big.erase(pos1);
        }

        auto pos1 = small.end(); pos1 --;
        auto pos2 = big.begin(); 
        while(*pos1 > *pos2)
        {
            big.insert(*pos1); small.insert(*pos2);
            big.erase(pos2); small.erase(pos1);
            pos1 = small.end(); pos1 --;
            pos2 = big.begin(); 
        }
        cout << (*pos2) << endl;
        // cout << "small: " ; print(small);
        // cout << "big:   " ; print(big);
    }

}

int main()
{
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int T = 1;
	// cin >> T;
    while (T --)
    {
        solv();
    }
    return 0;
}