Задать вопрос
  • Как из критерия унимодальности следует унимодальность функции?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    В унимодальной функции разности соседних элементов сначала неотрицательные а потом неположительные. И наоборот, если разности такие, то, очевидно, сначала функция возрастает (возможно, ступенчато) а потом убывает.

    Вы доказали, что частичные разницы не возрастают. Тут могут быть 3 варианта:
    1) они все неотрицательные. Функция унимодальна (монтонность с максимумом в конце - частный случай унимодальности).
    2) они все неположительные. Монотонно убывающая функция.
    3) есть и положительные и отрицательные. Но раз разности не могут возрастать, после первого 0 могут идти только нули а после отрицательного только отрицательные. А заначит разности выглядят ровно так, как у унимодальной функции.
    Ответ написан
    Комментировать
  • Почему в Python последовательность append-ов суммируется в O(n), а не в O(n logn)?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    а общее число перераспределений для n добавлений уменьшается как O(logn). Почему тогда в таком случае для n последовательности append-ов общая сложность равна O(n), а не O(n logn)?


    Потому что эти распределения разного размера. Первое - совсем маленькое. Второе чуть больше и т.д. Чтобы суммарно было O(n Log n), каждое из них должно быть пропорционально n.

    1+4+10+⋯≤O(n)


    Вот это и есть ответ. Первые слагаемые маленькие. Получается геометрическая прогрессия, которая дает линейную сумму от n.
    Ответ написан
    Комментировать
  • Почему в Python последовательность append-ов суммируется в O(n), а не в O(n logn)?

    AshBlade
    @AshBlade
    Просто хочу быть счастливым
    Потому что, здесь вступает в игру такое понятие как амортизированная сложность. Для динамических массивов, которые увеличиваются в несколько раз (т.е. не + 10, а *2 например), амортизированная сложность - O(1).
    Поэтому, у тебя O(n) * O(1) = O(n) (амортизированное)
    Ответ написан
    Комментировать
  • Как доказать что мы действительно не пропустим такую пару i,j которая дает правильный ответ в методе двух указателей?

    Alexandroppolus
    @Alexandroppolus
    кодир
    мы стартуем с i = 0 и j = M-1. Пусть ближайшее решение находится в индексах i0, j0

    рассмотрим возможные состояния:
    1) мы уже в (i0, j0), решение найдено
    2) мы в (i0, b), где b > j0. Здесь сумма больше чем С, мы просто уменьшаем j до j0 и приходим в п.1
    3) мы в (a, j0), где a < i0. Сумма меньше С, увеличиваем i до i0, приходим в п1
    4) мы в (a, b), где a < i0 и b > j0. Поскольку i может только увеличиваться, а j - только уменьшаться, то выйдем на п.2 или п.3, а оттуда на п.1

    Поскольку стартовали мы гарантированно из состояния 1...4, то все прочие состояния невозможна, потому что кейсы 1...4 уводят на п.1

    Вывод: мы не проскочим решение (i0, j0).

    ps: для наглядности можно разместить все точки (i, j) на координатной плоскости и заметить, что (i0, j0) - не просто точка, которую можно "обойти": она задает прямоугольник, в котором мы находимся на старте и из которого мы не выйдем, перепрыгнув через сторону.
    Ответ написан
    Комментировать
  • Как доказать что мы действительно не пропустим такую пару i,j которая дает правильный ответ в методе двух указателей?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    В такой реализации это плохо видно, но можно переписать основной цикл так:
    j = Len(B)-1
    for i in range(len(A)):
      while j >= 0 and A[i] + B[j] > c:
        --j;
      if A[i] + B[j] == c:
        found = True
        break


    В этом случае после цикла while поддерживается инвариант, что a[i]+b[j] <= c и это максимальное такое j.
    Ведь, если этот инвариант поддерживался для пердыдущей итерации, то у нас было a[i-1] +b[j] <=c и a[i-1]+b[j+1]>c. Отсюда получается, a[i]+b[j+1] >= a[i-1]+b[j+1] > c. Т.е. если мы уменьшим j в цикле while инвариант останется действовать - это будет самое большое j, т.ч. a[i]+b[j] <= c.

    А этот инвариант гарантирует, что когда в цикле по i переберется значение из ответа, j гарантированно будет указываать на j из ответа. Потому что, если существуют i', j', т.ч. a[i']+b[j'] = c, то можно увеличить j' пока b там не меняется, т.ч. b[j']>b[j'], отсюда получается a[i']+b[j'] <=c и a[i']+b[j+1] > c - а это и есть наш инвариант. Т.е. на итерации i=i' найдется именно j=j'.
    Ответ написан
    3 комментария
  • Как пользоваться Visual Studio Code на MacOS?

    otdameskapizm
    @otdameskapizm
    Помог ответ? Отметь решением...
    В settings.json добавьте "code-runner.runInTerminal": true, и должно быть вам счастье
    После этого в терминале появиться возможность ввода данных
    Ответ написан
    4 комментария