Creating ordered multiset with correctly working find()

為{幸葍}努か 提交于 2021-02-11 06:26:10

问题


I tried to create ordered multiset with such code:

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace std;
using namespace __gnu_pbds;

typedef long long ll;

template <class type1>
using ordered_multiset = tree <type1, null_type, less_equal <type1>, rb_tree_tag, tree_order_statistics_node_update>;

ordered_multiset <ll> kek;

int main()
{
    kek.insert(1); kek.insert(1);
    kek.insert(2); kek.insert(2); kek.insert(2);
    kek.insert(3);
    cout << (kek.find(2) == kek.end()) << endl;
}

But find() cant find any number because of using less_equal < ll > comparator instead of less < ll >. So, how to save dublicates in sorted set with working right find()?


回答1:


From the gnu docs here

Brace onself: this library does not contain containers like std::multimap or std::multiset. Instead, these data structures can be synthesized via manipulation of the Mapped template parameter.

There is no way to use this data structure for a multiset without some boiler plate of your own. For example your might do something like the following (though this is an unsafe incomplete implementation)

template <class T>
class multiset_equal_list {
    friend operator<(const multiset_equal_list<T>&, const T&);
private:
    mutable std::vector<T> equals;
public:
    bool operator<(const T& arg) const { return equals[0] < arg; }
    void add_equal(const T& arg) const { equals.push_back(arg); }
}


template <class T>
class my_multiset {
private:
    std::set<multiset_equal_list<T>> values; //instead of set, you can use the __gnu_pbds tree
public:
    void insert(const T& arg) {
        auto it = values.lower_bound(arg);
        if (it == values.end() || (*it < arg)) {
            multiset_equal_list<T> to_add;
            to_add.add_equal(arg);
            values.insert(it, to_add);
        } else { //they are equal
            it->add_equal(arg);
        }
    }
}

The link goes more into how you might approach the problem in different ways, but you are likely better off rolling your own or using an existing library that has all the functionality you want in a more portable standard way.

Note that the reason using std::less_equal does not work for you is because tree (and set and multiset etc.) determine equivalence if the comparison evaluates false for both. eg. a is equivalent to b if !(a < b) && !(b < a). So using less_equal that can never be the case (barring overloading)



来源:https://stackoverflow.com/questions/51969851/creating-ordered-multiset-with-correctly-working-find

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!