[Luogu] P1168 Median

topic description

Given a non-negative integer sequence A i A_i of length N NAi, for all 1 ≤ k ≤ ( N + 1 ) / 2 1≤k≤(N+1)/21k(N+1 ) / 2 , exportA 1 A_1A1, A 1 ∼ A 3 A_1 \yes A_3A1A3, …, A 1 ∼ A 2 k − 1 A_1 \sim A_{2k - 1}A1A2k 1 _median of . Namely the first 1 , 3 , 5 , … 1,3,5,…1,3,5,... the median of the numbers.

input format

1st 11 row is a positive integerNNN , represents the sequence length.

Second 22 rows containNNN non-negative integersA i ( A i ≤ 1 0 9 ) A_i (A_i ≤ 10^9)Ai(Ai109)

output format

Total ( N + 1 ) / 2 (N + 1 ) / 2(N+1 ) / 2 lines,iiand rowsA1 , A 3 , … , A 2 k − 1 A_1, A_3, …, A_{2k - 1}A1,A3,,A2k 1 _median of .

Input and output samples

enter

7
1 3 5 7 9 11 6

output

1
3
5
6

Instructions/Tips

For 20 % 20\%20 % of data,N ≤ 100 N ≤ 100N100

For 40 % 40\%4 0 % of data,N ≤ 3000 N ≤ 3000N3000

For 100 % 100\%1 0 0 % of data,N ≤ 100000 N ≤ 100000N100000

topic link

https://www.luogu.com.cn/problem/P1168

answer

data structure:

priority_queue<int, vector<int>, less<int> > pq;

train of thought

Suppose now there is a sorted array, as follows:

insert image description here

We can draw the following conclusions:

1. First, the left side of the median is smaller than the median;

2. Secondly, the right side of the median is greater than the median;

3. The left side of the median is arranged in order from large to small;

4. The right side of the median is arranged in order from small to large;

Then according to the principle of the heap, the top of the left heap stores the largest value to the left of the median, and the top of the right heap stores the smallest value to the right of the median, so that the median can be accurately located.

We construct two heaps, the left is the big root heap, and the right is the small root heap. Since the median is in the middle, we put it in the left big root heap, and of course it can also be placed in the right heap.

So how do we do it?

First, we read the first number into left leftl e ft queue, then this number is naturally the median, and it will be output .

Then, we read in two numbers each time, set x, yx, yx , y , for these two numbers, if it is less than the original median, that isleft.top ( ) left.top()l e f t . t o p ( ) , then wepush it pushpush l e f t left l e f t inside, otherwise we push itpushpush r i g h t right r i g h t inside. Why do you do this? becauseleft leftl e f t stores a number smaller than the median, so put the number smaller than the original median intoleft leftl e f t inside, likewise,left leftl e f t stores a number larger than the median, so put the number larger than the original median intoright rightr i g h t inside.

because we want to keep left leftThe elements in l e f t are better than right rightThere is one more r i g h t (because left leftleft 里比 r i g h t right There is an extra median in r i g h t ). So ifx , yx,yx,y are put intoleft leftleft r i g h t right r i g h t inside. Then this requirement must be broken at this time, so we need to maintain the two queues, letleft leftThe elements in l e f t are better than right rightThere is one more in r i g h t .

Case 1: x , yx,yx,y p u s h push push l e f t left left

insert image description here

because itself left leftThe elements in l e f t are more than right rightThere are more elements in r i g h t than 1 11 个,本来是 l e f t . s i z e ( ) − 1 = = r i g h t . s i z e ( ) left.size()-1 == right.size() left.size()1==right.size() ,然后变成了 l e f t . s i z e ( ) − 1 > r i g h t . s i z e ( ) left.size()-1 > right.size() left.size()1>r i g h t . s i z e ( ) , for this case, specifyleft leftThe top element of the heap in l e f t is no longer the median, and the top of the heap is larger than the median, then we need toleft leftl e f t move the top element toright rightr i g h t inside.

Case 2: x , yx,yx,y p u s h push push r i g h t right right

insert image description here

because itself left leftThe elements in l e f t are more than right rightThere are more elements in r i g h t than 1 11 个,本来是 l e f t . s i z e ( ) − 1 = = r i g h t . s i z e ( ) left.size()-1 == right.size() left.size()1==right.size() ,然后变成了 l e f t . s i z e ( ) = = r i g h t . s i z e ( ) − 1 left.size() == right.size()-1 left.size()==right.size()1 , for this caseright rightThe top element in the r i g h t heap is the median, but in order to maintain the relationship between the two queue sizes, right rightr i g h t move the top element toleft leftl e ft inside .

code show as below:

#include <bits/stdc++.h>

using namespace std;

int main() {
    
    
    int N;
    cin >> N;

    priority_queue<int, vector<int>, less<int> > left;
    priority_queue<int, vector<int>, greater<int> > right;

    int a;
    cin >> a;
    left.push(a);
    cout << left.top() << endl;

    int t = (N + 1) / 2 - 1;
    while (t--) {
    
    
        int x, y;
        //每次读入两个数
        cin >> x >> y;
        //读入的数小于原来的中位数,则放入到右侧小顶堆
        if (x <= left.top()) {
    
    
            left.push(x);
        } else {
    
    
            right.push(x);
        }

        if (y <= left.top()) {
    
    
            left.push(y);
        } else {
    
    
            right.push(y);
        }
        //如果左边堆的大小减一之后还比右堆大,说明此次操作把 x 和 y都push进了left堆,需要维护两个堆的大小关系
        if (left.size() - 1 > right.size()) {
    
    
            int temp = left.top();
            left.pop();
            right.push(temp);
        }
        //如果右边堆的大小比左堆大,说明此次操作把 x 和 y都push进了right堆,需要维护两个堆的大小关系
        if (right.size() > left.size()) {
    
    
            int temp = right.top();
            right.pop();
            left.push(temp);
        }
        cout << left.top() << endl;
    }
    return 0;
}

February 3, 2021

Guess you like

Origin blog.csdn.net/BWQ2019/article/details/113641495