Template
, Data Structure
void Balance() {
if(sizSmall > sizBig + 1) {
Big.push(Small.top()), sizBig++;
Small.pop(), sizSmall--;
}
else if(sizSmall < sizBig) {
Small.push(Big.top()), sizSmall++;
Big.pop(), sizBig--;
}
}
Lưu ý : Nhớ xét riêng trường hợp
void add() {
if(Small.empty()) Small.push(x), sizSmall++;
else {
int median = Small.top();
if(x > median) Big.push(x), sizBig++;
else Small.push(x), sizSmall++;
}
Balance();
}
Lưu ý : Ta sẽ cần phải có một giá trị quản lý
void Paid() {
while(!OweBig.empty() && OweBig.top() == Big.top())
OweBig.pop(), Big.pop();
while(!OweSmall.empty() && OweSmall.top() == Small.top())
OweSmall.pop(), Small.pop();
}
void rev() {
if(x == Small.top()) Small.pop(), sizSmall--;
else if(x < Small.top()) OweSmall.push(x), sizSmall--;
else if(x == Big.top()) Big.pop(), sizBig--;
else if(x > Big.top()) OweBig.push(x), sizBig--;
Paid();
Balance();
}
for(int i = 1 ; i <= q ; ++i) {
cin >> c >> x;
if(c == '+') add();
else rev();
ans[i] = Small.top();
}
for(int i = 1 ; i <= q ; ++i) cout << ans[i] << '\n';
Time:
Space:
#include <bits/stdc++.h>
#pragma GCC optimize("O2")
using namespace std;
const int N = 1e5 + 7;
const double eps = 1e-9;
template <typename X> using V = vector<X>;
template <typename X>
bool minimize(X &a, const X b) {
if(a > b + eps) return a = b, 1;
else return 0;
}
template <typename X>
bool maximize(X &a, const X b) {
if(a + eps < b) return a = b, 1;
else return 0;
}
int q, sizSmall, sizBig, x;
char c;
priority_queue<int, V<int>, greater<int>> Big, OweBig;
priority_queue<int> Small, OweSmall;
void Paid() {
while(!OweBig.empty() && OweBig.top() == Big.top())
OweBig.pop(), Big.pop();
while(!OweSmall.empty() && OweSmall.top() == Small.top())
OweSmall.pop(), Small.pop();
}
void Balance() {
if(sizSmall > sizBig + 1) {
Big.push(Small.top()), sizBig++;
Small.pop(), sizSmall--;
}
else if(sizSmall < sizBig) {
Small.push(Big.top()), sizSmall++;
Big.pop(), sizBig--;
}
Paid();
}
void add() {
if(Small.empty()) Small.push(x), sizSmall++;
else {
int median = Small.top();
if(x > median) Big.push(x), sizBig++;
else Small.push(x), sizSmall++;
}
Balance();
}
void rev() {
if(x == Small.top()) Small.pop(), sizSmall--;
else if(x < Small.top()) OweSmall.push(x), sizSmall--;
else if(x == Big.top()) Big.pop(), sizBig--;
else if(x > Big.top()) OweBig.push(x), sizBig--;
Paid();
Balance();
}
int ans[1000002];
int main () {
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin >> q;
for(int i = 1 ; i <= q ; ++i) {
cin >> c >> x;
if(c == '+') add();
else rev();
ans[i] = Small.top();
}
for(int i = 1 ; i <= q ; ++i) cout << ans[i] << '\n';
}
/*
@Author: SPyofgame
@License: Free to use
@Tag: Dynamic Median Data Structure
*/
#include <iostream>
#include <cassert>
#include <vector>
#include <queue>
using namespace std;
/// Data Structure that
/// - Insert element in O(log size)
/// - Erase element in O(log size)
/// - Find median in O(log size)
/// - Constant Factor: As high as C++std::priority_queue
template<typename T>
struct Dynamic_Median
{
/// Diffrent Size | Expected Ratio: |L| >= |R| & |L| - |R| <= 1
int diff = 0;
/// Value can be duplicated
/// Value Array
priority_queue<T, vector<T>, less<T> > L;
priority_queue<T, vector<T>, greater<T> > R;
/// Erasing Queue
priority_queue<T, vector<T>, less<T> > LEQ;
priority_queue<T, vector<T>, greater<T> > REQ;
/// Balance two array with expected ratio: |L| >= |R| & |L| - |R| <= 1
/// Return value: void
/// Parameter: NULL
/// Complexity: O(log size)
/// Requirement: ALL OTHER FUNCTION use this on top
/// Run-time-error: |L| = 0 or |R| = 0 while balancing
/// Suspect (diff) behaved wrongly
void balance()
{
if (diff > 1)
{
assert(L.size());
R.push(L.top());
L.pop();
diff -= 2;
}
else if (diff < 0)
{
L.push(R.top());
R.pop();
diff += 2;
}
while (REQ.size() && REQ.top() == R.top()) REQ.pop(), R.pop();
while (LEQ.size() && LEQ.top() == L.top()) LEQ.pop(), L.pop();
}
/// Find median of array S = (L + R)
/// Return value: S[n / 2] if n = |S| is even
/// S[(n - 1) / 2] if n = |S| is odd
///
/// Parameter: NULL
/// Complexity: O(log size)
/// Run-time-error: Balance() behaved wrongly
/// |L| is empty after balancing
T median()
{
balance();
assert(L.size());
return L.top();
}
/// Find median of array S = (L + R)
/// Return value: S[n / 2] if n = |S| is even
/// S[(n + 1) / 2] if n = |S| is odd
///
/// Parameter: NULL
/// Complexity: O(log size)
/// Run-time-error: Balance() behaved wrongly
/// |R| is empty after balancing
T median2()
{
balance();
assert(R.size());
return R.top();
}
/// Insert (value) to array
/// Return value: void
/// Parameter: <T> value
/// Complexity: O(log size)
/// Run-time-error: Balance() behaved wrongly
void insert(const T &value)
{
balance();
if (L.empty() || value <= median())
L.push(value), ++diff;
else
R.push(value), --diff;
}
/// Erase (value) from array
/// Return value: void
/// Parameter: <T> value
/// Complexity: O(log size)
/// Run-time-error: Balance() behaved wrongly
/// |L| = 0 or |R| = 0 while erasing
void erase(const T &value)
{
balance();
if (value <= median()) /// If median() cost is high
{ /// Then please precalculate it
--diff;
(value == median()) ? L.pop() : LEQ.push(value);
}
else
{
++diff;
(value == median2()) ? R.pop() : REQ.push(value);
}
}
};
int main()
{
ios::sync_with_stdio(NULL);
cin.tie(NULL);
int q;
cin >> q;
Dynamic_Median<int> S;
while (q-->0)
{
char operation;
cin >> operation;
int value;
cin >> value;
if (operation == '+')
S.insert(value);
else
S.erase(value);
cout << S.median() << "\n";
}
return 0;
}