I think you can solve the problem using two std::map . One for the smaller half of objects (mapL) and the second for the other half (mapU). When you have an insert operation. This will be any case:
- add an element to mapU and move the smallest element to mapL
- add an element to mapL and move the largest element to mapU
In case the cards are of different sizes, and you insert an element into a number with fewer elements that you skip in the move section. The basic idea is that you keep the cards balanced, so the maximum size difference is 1 element. As far as I know, STL all operations should work in O (ln (n)) time. Access to the smallest and largest element on the map can be done using an iterator. When you have a request for n_th position, just check the size of the maps and return the largest element in mapL or the smallest element in mapR.
The above use case is for insertion only, but you can also extend it to delete items, but you have to keep track of which card holds the item or try to remove from both.
Here is my code using an example:
#include <iostream> #include <string> #include <map> using namespace std; typedef pair<int,string> pis; typedef map<int,string>::iterator itis; map<int,string>Left; map<int,string>Right; itis get_last(map<int,string> &m){ return (--m.end()); } int add_element(int key, string val){ if (Left.empty()){ Left.insert(make_pair(key,val)); return 1; } pis maxl = *get_last(Left); if (key <= maxl.first){ Left.insert(make_pair(key,val)); if (Left.size() > Right.size() + 1){ itis to_rem = get_last(Left); pis cpy = *to_rem; Left.erase(to_rem); Right.insert(cpy); } return 1; } else { Right.insert(make_pair(key,val)); if (Right.size() > Left.size()){ itis to_rem = Right.begin(); pis cpy = *to_rem; Right.erase(to_rem); Left.insert(*to_rem); } return 2; } } pis get_mid(){ int size = Left.size() + Right.size(); if (Left.size() >= size / 2){ return *(get_last(Left)); } return *(Right.begin()); } int main(){ Left.clear(); Right.clear(); int key; string val; while (!cin.eof()){ cin >> key >> val; add_element(key,val); pis mid = get_mid(); cout << "mid " << mid.first << " " << mid.second << endl; } }
jethro
source share