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

Автор thanhchauns2, история, 21 месяц назад, По-английски

Hi there!

In this blog I would like to share some of the code snippets that can shorten your time in future contests. Of course, I'll ignore the "international snippets"

like:

Sometimes you may find typing the identical thing again and again is boring, this blog is about some method that a few people use to get rid of them (or just only me).

So, let's get started.

Scanning/printing the whole vector in a single std::cin/std::cout

Snippet
Usage

Scanning/printing std::pair

Snippet
Usage

Ordered set and ordered multiset

Snippet
Usage

Short declaration of 2D and 3D vectors

Snippet
Usage

Erase repeated neighbor elements

Snippet
Usage

Prime test for large numbers

Snippet

Longest Increasing Subsequence

Snippet

Longest Strictly Increasing Subsequence

Snippet

Some snippets are mine, some are taken from the internet. If you want to add some snippets on the blog, please let me know in the comment section.

You can read more about ordered_set and ordered_multiset here: https://codeforces.com/blog/entry/11080

Thanks for reading! Hope this can help you.

A little surprise
  • Проголосовать: нравится
  • +37
  • Проголосовать: не нравится

»
21 месяц назад, # |
  Проголосовать: нравится +145 Проголосовать: не нравится
A little surprise
»
21 месяц назад, # |
  Проголосовать: нравится +51 Проголосовать: не нравится

I prefer kactl's prime test as it's deterministic

»
21 месяц назад, # |
  Проголосовать: нравится -32 Проголосовать: не нравится

You missed something very important sir. Without that, this blog would be incomplete. Binary Search!

def binarySearch(arr, key):   # search lower bound(key)
    beg, end = 0, len(arr) - 1
    found = False
    ind = -1
    while beg <= end:
        mid = beg + (end - beg) // 2    # to avoid mid overflow
        if key == arr[mid]:             # condition
            found = True
            ind = mid
            # end = mid - 1     # lower bound
            break                  # traditional BS
        elif key < arr[mid]:
            end = mid - 1
        else:
            beg = mid + 1
    if not found:     # insertion point = beg (beg < end == True)
        return -1 
    else:
        return ind

I guess Um_nik would be proud of me on this day :P

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

    I guess we can use simple binary_search (start,end,key) function.

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

    Since you thought it is a good idea to tag me: this implementation is an abomination, you should be ashamed of yourself.

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

    Since someone posted an implementation of binary search, I can't not use this opportunity to popularize lifting-style binary search.

    int ans = 0;
    for (int k = 1 << 29; k != 0; k /= 2)
      if (is_ok(ans + k))
        ans += k;
    

    which finds the greatest integer $$$x$$$ in $$$[0, 2^{30} - 1]$$$ such that is_ok(x) is true (assuming the function is binary-searchable, of course).

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

      Just wondering, is it better to use OR operation instead of addition? In my template which I copied uses OR instead.

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

        no

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

        Very likely it is the same; if OR is any faster, the compiler should be smart enough to see that it can be used.

        Also, if you do this thing on floating-point numbers (replacing k != 0 with k > EPS), you can't use |= anymore but can use +=.

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

          it also doesn't work if u start at anything other than 0

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

    When did binary search get so complicated

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

Great blog but I prefer conventional way , because it lets me know the code structure during debugging

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

One short tip that will shorten your time:

You can delete many template <typename T> if you use auto.

  • »
    »
    21 месяц назад, # ^ |
    Rev. 3   Проголосовать: нравится -10 Проголосовать: не нравится

    Not quite, the auto isn't that magical. To be more precise auto can only be use with lamda function, and some struct/class variables

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

How about providing ordered set and ordered map instead of ordered multiset? It would be helpful to do this and teach them to use the comparators with equality (less_equal, etc) instead for a multiset. This is an example snippet:

Snippet
»
21 месяц назад, # |
  Проголосовать: нравится +23 Проголосовать: не нравится

LIS is obviously wrong.

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

    Yes, I forgot to mention it is used for finding the longest LIS available's length, not itself.

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

      In that case it is better to return S.size(), not the multiset itself. Also, multiset is too excessive here, vector would be just better.

      • »
        »
        »
        »
        21 месяц назад, # ^ |
        Rev. 3   Проголосовать: нравится +102 Проголосовать: не нравится

        The shortest implementation I know is this (if you need only the length):

        // d = {INF, ... INF (n times)}
        for (int x : arr) *lower_bound(d.begin(), d.end(), x) = x;
        // length == position of first INF in d
        

        Amazing how this not so easy algorithm is a one-liner.

        And upper_bound makes it non-decreasing.

»
21 месяц назад, # |
  Проголосовать: нравится -10 Проголосовать: не нравится

also let me advertise this (probably not so) short snippet which I like to call the "Universal Container Input". Simply said, it lets you use std::cin for almost any iterable container whose value type is one that could be used with std::cin (which, in turn, could be another container type). The only exception is the dynamically allocated array, which I have not found a way. Here's the snippet:

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

    (oh, and std::string and char* will not use this, in this case the overload is useless and therefore I made them not use this)

»
21 месяц назад, # |
Rev. 2   Проголосовать: нравится +11 Проголосовать: не нравится

hard to remember last time I needed to find LIS (except maybe in last 10 years)

about multivectors: c++17 allows to use $$$O(d)$$$ vectors instead of $$$O(d^2)$$$ to define required:

vector a(n, vector(m, vector<int>(k)))

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

I'm very curious about the gnu c++ segment tree... could someone explain how it works and how to use it?