Блог пользователя nchn27

Автор nchn27, история, 5 лет назад, По-английски

In use, multiset seems more versatile than priority queue due to the fact that you can remove things other than the first element. In C++, when would priority_queue be used instead of multiset?

  • Проголосовать: нравится
  • +1
  • Проголосовать: не нравится

»
5 лет назад, # |
  Проголосовать: нравится +13 Проголосовать: не нравится

Priority_queue is faster, but usually for competitive programming using multiset is better since it is more convenient and for problems that arent very tight it makes no difference.

  • »
    »
    4 года назад, # ^ |
    Rev. 2   Проголосовать: нравится -66 Проголосовать: не нравится

    How is Priority_queue faster than a multiset?

    Wont Deletion through an iterator take constant time in a multiset where as pop takes log(n) time in priority queue

    • »
      »
      »
      4 года назад, # ^ |
        Проголосовать: нравится +20 Проголосовать: не нравится

      I don't know the implementations in C++ nor have I benchmarked the structures, but I would definitely expect priority queue to be faster, maybe even a lot faster. Why would you expect otherwise?

      The functions of a priority queue are a subset of the functions of a multiset, if the latter is faster then the former is useless.

      You can implement a priority queue through a heap structure, while for a multiset you need a balanced binary tree structure, which is significantly heavier.

      • »
        »
        »
        »
        4 года назад, # ^ |
          Проголосовать: нравится -56 Проголосовать: не нравится

        Agreed, but Wont Deletion through an iterator take constant time in a multiset where as pop takes log(n) time in priority queue

        • »
          »
          »
          »
          »
          4 года назад, # ^ |
            Проголосовать: нравится +16 Проголосовать: не нравится

          It may be so, but that's not a great way to look at it. If you add $$$N$$$ elements and then remove them all, both priority queue and multiset will be $$$O(N log N)$$$ (and in fact no structure is faster than that, because you'd break the sorting complexity lower bound). Even if multiset is quicker in the deletion part, it likely pays a price for that during the addition part.

          It may be interesting to properly compare them, but I'd be quite surprised if multiset turns out to be faster, as my experience has showed that set/map in C++ are incredibly heavy.

        • »
          »
          »
          »
          »
          4 года назад, # ^ |
          Rev. 2   Проголосовать: нравится +8 Проголосовать: не нравится

          As far as I know, multiset is implemented as a balanced binary tree as Enchom mentioned. Since it should be 'balanced' after insertion and deletion, it has to do some 're-balancing' (algorithms can vary by implementation, but generally rotating trees). Unless it does that job, there might be some possbile occasions which a sequence of insertion and deletion makes multiset's internal implementation tree unbalanced and makes operation after that very slow (up to O(n))

          To sum up, priority queue is a heap structure, which takes $$$O(\log n)$$$ time to delete top element. Multiset is a balanced binary search tree, which takes up to $$$O(\log n)$$$ time to delete anything and then assuring balance. Latter can be a lot slower (bigger constant factor).

          Currently priority queue is somewhere 1.5x to 2x faster than multiset with compiler optimizations. (Depends on if you turned -O2 on, and bunch of other factors, including your compiler version and OS) There are some benchmarks in stackoverflow, which I haven't throughly read yet.

          Edit : my friend pointed out that my numbers are wrong.

          • »
            »
            »
            »
            »
            »
            4 года назад, # ^ |
            Rev. 2   Проголосовать: нравится +24 Проголосовать: не нравится

            According to this reference, he is actually right that deletion is amortized constant. I ran a few quick tests and indeed multiset deletion seems faster than priority queue deletion.

            However, as I suspected and mentioned in my other comment, this is at the cost of a very slow addition in multiset compared to priority queue. Since you can't delete more elements than you add, I can't imagine a scenario where you'd prefer multiset only due to the faster deletion.

            • »
              »
              »
              »
              »
              »
              »
              4 года назад, # ^ |
                Проголосовать: нравится +1 Проголосовать: не нравится

              Oh, I misread the question and considered erasing by value. I was talking about wrong thing then. Thanks for pointing it out.

            • »
              »
              »
              »
              »
              »
              »
              4 года назад, # ^ |
                Проголосовать: нравится +10 Проголосовать: не нравится

              Right...

              Maybe as gratus907 said, Addition in Multiset would probably be slower due to ReBalancing Algorithms (Rotating Tree).

              Thanks once Again!

            • »
              »
              »
              »
              »
              »
              »
              4 года назад, # ^ |
                Проголосовать: нравится -29 Проголосовать: не нравится

              Amortised isn't worst case, that's still $$$O(\log)$$$.

              • »
                »
                »
                »
                »
                »
                »
                »
                4 года назад, # ^ |
                  Проголосовать: нравится 0 Проголосовать: не нравится

                Worst case may be o(log) but the average time, ie the amortized time is constant.

                Check out Enchom comment on this blog. He ran few tests, and found out that deletion in a multiset is faster than popping from a priority queue

                • »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  4 года назад, # ^ |
                    Проголосовать: нравится -7 Проголосовать: не нравится

                  Yes, I read the comments before posting, unsurprisingly. It's just that when you don't mention that you're talking about amortised complexity, the assumption is that it's worst case.

                  There are implementation tricks for faster insert/delete operations for a lot of structures, for example deletion flags on nodes and lazy rebalancing. That's why I'm more interested in a test where insert/delete is mixed with searching, but that comparison is tough because heap doesn't have searching.

                • »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  4 года назад, # ^ |
                    Проголосовать: нравится -10 Проголосовать: не нравится

                  "It's just that when you don't mention that you're talking about amortised complexity, the assumption is that it's worst case."

                  This is a widely misunderstood point about amortization, but it is actually completely independent from the concept of "worst case" or "average case". Classical analysis only considers complexity on a per-operation basis, whereas amortized complexity is about analyzing on a per-algorithm basis. There is a nice rigorous definition regarding potential functions here that shows that if you sum up the amortized complexity over a sequence of operations, it will necessarily be an upper bound for the standard complexity summed over that sequence of operations (note that "worst case" is never referenced in this definition).

                  I also don't think it's necessarily correct that people default to not talking about amortized analysis. I actually can't think of a scenario where the amortized complexity is better than non-amortized complexity and we don't default to amortized (std::vector::push_back, for example). Curious to hear if you have contrary examples, though. It's quite late for me so my recall could be bad.

              • »
                »
                »
                »
                »
                »
                »
                »
                4 года назад, # ^ |
                  Проголосовать: нравится 0 Проголосовать: не нравится

                What's your point? Why would we care specifically about worst case complexity in this discussion? It is worst case $$$O(logN)$$$ to delete one element, but $$$O(1)$$$ amortized. This means if you were to delete all $$$N$$$ elements it'd be $$$O(N)$$$.

                • »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  4 года назад, # ^ |
                    Проголосовать: нравится -35 Проголосовать: не нравится

                  Why would we care specifically about worst case complexity in this discussion?

                  Because that's normal?

                • »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  4 года назад, # ^ |
                    Проголосовать: нравится 0 Проголосовать: не нравится

                  Still don't get your point. Is your claim that when mixed with other operations, deletion will no longer be amortized $$$O(1)$$$? If that's true that's interesting, but I don't think it's easy to tell without knowing the specific implementation.

                • »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  4 года назад, # ^ |
                    Проголосовать: нравится 0 Проголосовать: не нравится

                  Not a claim, just one hypothesis. I'm wondering about the real implementation and what implementations there could be.

        • »
          »
          »
          »
          »
          4 года назад, # ^ |
            Проголосовать: нравится -22 Проголосовать: не нравится

          NO. Deletion of anything in a balanced binary tree requires rebalancing, which is $$$O(\log)$$$. Whether it's through an iterator is irrelevant.

      • »
        »
        »
        »
        4 года назад, # ^ |
          Проголосовать: нравится +4 Проголосовать: не нравится

        I think pq is faster since it is cache friendly. pq's are internally stored in a contiguous memory(like vector), While multiset's are not.

    • »
      »
      »
      4 года назад, # ^ |
      Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

      UPD : Deleted

»
4 года назад, # |
  Проголосовать: нравится -53 Проголосовать: не нравится

The comments on this blog made me re-realize how much I still have to learn to become a Master. XD

»
4 года назад, # |
  Проголосовать: нравится -92 Проголосовать: не нравится

Multisets and priority ques are used only on Div1 E-F problems and top onsite competitions like ICPC WF, and are not needed to score well in CF rounds.

Personally I have never seen a reasonable problem that would require priority que during my CP career, and believe me, I consider myself experienced competitive programmer.

  • »
    »
    4 года назад, # ^ |
      Проголосовать: нравится +23 Проголосовать: не нравится

    Too young too simple...

  • »
    »
    4 года назад, # ^ |
      Проголосовать: нравится +6 Проголосовать: не нравится

    20C - Dijkstra? is a classic problem that needs to be solved by Dijkstra algorithm with heap optimisation.

    • »
      »
      »
      4 года назад, # ^ |
        Проголосовать: нравится -45 Проголосовать: не нравится

      Hmm, it is still alpha contest when CF was new and Mike just copied tasks. There is no such problem in recent CF rounds (about last 2 or 3 years).

      • »
        »
        »
        »
        4 года назад, # ^ |
          Проголосовать: нравится +9 Проголосовать: не нравится

        What about 960B - Minimize the error? It's a Div. 1 + Div. 2 B with difficulty *1500.

        • »
          »
          »
          »
          »
          4 года назад, # ^ |
            Проголосовать: нравится -12 Проголосовать: не нравится

          It can be solved in $$$O(n \cdot (k_1 + k_2))$$$. $$$k_1$$$ times choose $$$i$$$ such that $$$a_i - b_i$$$ is largest and decrease $$$a_i$$$, then do the same for array $$$B$$$. I don't see how priority que or multiset can be utilized here.

          • »
            »
            »
            »
            »
            »
            4 года назад, # ^ |
              Проголосовать: нравится +6 Проголосовать: не нравится

            See the tutorial please.

            "This can be implemented using a priority queue or by sorting the array C and iterating over it."

            Although this problem has a solution which doesn't need priority queue, it seems that priority queue is well known by most competitive programmer according to the sentence.

            • »
              »
              »
              »
              »
              »
              »
              4 года назад, # ^ |
                Проголосовать: нравится -16 Проголосовать: не нравится

              Well, according to my comment above it's not well known. Or do you believe thousands of grey coders actually know multiset and priority_queue?

              • »
                »
                »
                »
                »
                »
                »
                »
                4 года назад, # ^ |
                  Проголосовать: нравится 0 Проголосовать: не нравится

                "Well, according to my comment above it's not well known." Well, I say something according to the tutorial because the tutorial is reliable. Is what you said reliable?

                "Or do you believe thousands of grey coders actually know multiset and priority_queue?" Of course grey coders don't know them, because they're Newbies. Most of them are amateur competitive programmers, maybe not even competitive programmers. They don't know multiset and priority_queue, but do you think they can solve div. 2 C~D? "Newbies don't know multiset and priority_queue" can't prove that multiset and priority_queue aren't well known.

                • »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  4 года назад, # ^ |
                    Проголосовать: нравится +11 Проголосовать: не нравится

                  I will bet most grey coders even at least know what it is lol. They may not know when to use it well, but even many grey coders know things fundamental things like that.

  • »
    »
    4 года назад, # ^ |
    Rev. 2   Проголосовать: нравится +14 Проголосовать: не нравится

    And 1314A - Recommendations only Div.1A using priority_queue. And it's only four weeks ago.

  • »
    »
    4 года назад, # ^ |
      Проголосовать: нравится +24 Проголосовать: не нравится

    You're just without experience to say such words.

  • »
    »
    4 года назад, # ^ |
    Rev. 2   Проголосовать: нравится +16 Проголосовать: не нравится

    And 527C - Glass Carving is a typical multiset problem in Codeforces. Only Div.2C which has a similar difficulty to Div.2D today.

  • »
    »
    4 года назад, # ^ |
      Проголосовать: нравится -8 Проголосовать: не нравится

    Bruh you are like if LanceTheDragonTrainer was a grey coder...

    • »
      »
      »
      4 года назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      Lol. Couldn't understand your English. But what do you think my rating really is?

      • »
        »
        »
        »
        4 года назад, # ^ |
        Rev. 3   Проголосовать: нравится 0 Проголосовать: не нравится

        I assume quite good. You seem to know what you're talking about on a variety of cp topics and most people (unlike cyan i responded to) would need to be quite good to have the audacity to make bold statements and say stuff like "and believe me, I consider myself experienced competitive programmer" or belittle people for having low color. My guess would be IM or GM.

        • »
          »
          »
          »
          »
          4 года назад, # ^ |
            Проголосовать: нравится +4 Проголосовать: не нравится

          Wow. You just made my day. If I ever return to Competitive Programming, I will train hard and share my knowledge with interested parties, to repay your praise.

  • »
    »
    4 года назад, # ^ |
      Проголосовать: нравится -21 Проголосовать: не нравится

    Virgin with 2 inches tool: "size doesn't matter, most girls can't even tell the difference"

»
4 года назад, # |
  Проголосовать: нравится +13 Проголосовать: не нравится

i dont use multiset nor i use qriority queue ,i use set<pair<int,int>> where i store value in pair.first and index in pair.second automatically it becomes mutiset + it supports more functions like searching a specific element after a particular index etc.. :)

»
4 года назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Also priority queue construct in O(n)

  • »
    »
    4 года назад, # ^ |
      Проголосовать: нравится +11 Проголосовать: не нравится

    what is the syntax for constructing the priority queue in O(n) time because if i have n elements initially and i want to construct the priority queue then i have to add every element using push() and for each, it will take logn time so overall complexity is O(nlogn) only.