Post

数据流动态中位数查询器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <bits/stdc++.h>
using namespace std;

// 数据流动态中位数查询器
class MediumFinder {
public:
  priority_queue<int> small;                          // 大根堆
  priority_queue<int, vector<int>, greater<int>> large; // 小根堆

  void make_balance() {
    if (small.size() >= large.size() + 2) {
      int top = small.top();
      small.pop();
      large.push(top);
    } else if (small.size() < large.size()) {
      int top = large.top();
      large.pop();
      small.push(top);
    }
  }

  void push(int item) {
    if (small.empty() || item <= small.top())
      small.push(item);
    else
      large.push(item);

    make_balance();
  }

  double get_medium() {
    if (small.size() == large.size()) {
      return (small.top() + large.top()) / 2.0;
    } else {
      return small.top();
    }
  }
};

int main() {
  int t;
  cin >> t;
  while (t--) {
    int n;
    cin >> n;
    vector<int> a(n);
    vector<int> b(n - 1);
    for (int i = 0; i < n; i++)
      cin >> a[i];
    for (int i = 0; i < n - 1; i++)
      cin >> b[i];

    // 逆向思考
    // 由于b中最小值为1,所以不会删除a[0],所以到最后的中位数必然是a[0]
    vector<double> mediums = {(double)a[0]};
    MediumFinder medium_finder;
    medium_finder.push(a[0]);
    for (int i = b.size() - 1; i >= 0; i--) {
      medium_finder.push(a[b[i]]);
      mediums.push_back(medium_finder.get_medium());
    }

    reverse(mediums.begin(), mediums.end());
    for(auto m : mediums) {
        if (m - int(m)) printf("%.1f ", m);
        else printf("%d ", int(m));
    }
    cout<<endl;
  }
  return 0;
}
This post is licensed under CC BY 4.0 by the author.