Нахождение подпоследовательности (маленький-большой-средний)

Учитывая список из n неповторяющихся целых чисел L:=(x1,...,xn), разработать алгоритм, который решает, есть ли в L xi1, xi2, xi3, так что i1 ниже, чем i2, i2 ниже, чем i_3, xi1 ниже, чем xi3, а xi3 ниже, чем xi2. Требуется только ответ "да-нет".

В заявлении также предлагается использовать стратегию "разделяй и властвуй".

Моя попытка была следующей:

Я читаю вектор слева направо

  • Если список изменяется от увеличения к уменьшению, то становится ясно, что число последних прочитанных меньше максимума текущего списка чтения. Поэтому, если он больше минимума текущего списка, мы можем остановиться.
  • Если список меняется от уменьшения к увеличению, то я ищу первое число m в списке, которое является локальным минимумом, и оно меньше, чем последнее прочитанное число c. И тогда я ищу локальный максимум, появляющийся после m, который больше чем c.
  • Если список продолжает увеличиваться, мы делаем то же, что и на предыдущем шаге.
  • Если список продолжает уменьшаться, ничего не делайте.

Так что сложность нлогн. Я думаю, что стратегия хорошая, но онлайн-судья отклонил ее. Я не знаю, происходит ли это из-за глупой ошибки или потому что стратегия действительно неверна.

#include <iostream>
#include <algorithm>
#include <map>

using namespace std;

bool solveCase();
bool increasingCase(map<int, int> & mins, map<int, int> & maxs,
        pair<map<int, int>::iterator, bool> & lastMaxInserted,
        const int & current);
void ignoreStuff();

int main() {
    while (solveCase())
        ;
    return 0;
}

bool solveCase() {
    /*---Reading the number of children---*/
    int N;
    if (scanf("%d", &N) == EOF) {
        return false;
    }
    /*---Used variables---*/
    int globalMax;
    int globalMin;
    map<int, int> maxs;
    map<int, int> mins;
    int localMin;
    int localMinPos;
    bool increasing;
    pair<map<int, int>::iterator, bool> lastMaxInserted;
    int old;
    int current;
    /*-----Reading the first two children-----*/
    /*--Reading the first children--*/
    scanf("%d", &old);
    globalMax = old;
    globalMin = old;
    /*--Reading the second children--*/
    scanf("%d", &current);
    if (current > old) { /*The sequence starts increasing*/
        increasing = true;
        globalMax = current;
        localMin = old;
        localMinPos = 0;
    } else { /*The sequence starts decreasing*/
        increasing = false;
        globalMin = current;
        lastMaxInserted = maxs.insert(pair<int, int>(old, 0));
    }
    old = current;
    /*-----Reading the rest-----*/
    for (int i = 2; i < N; i++) {
        scanf("%d", &current); /*Reading a child*/
        if (!increasing) { /*--The sequence was decreasing--*/
            if (current < old) { /*The sequence keeps decreasing*/
                globalMin = min(current, globalMin);
            } else { /*The monotony changes*/
                localMin = old;
                localMinPos = i - 1;
                if (increasingCase(mins, maxs, lastMaxInserted, current)) {
                    printf("ELEGIR OTRA\n");
                    ignoreStuff(); /*Ignoring the rest*/
                    return true;
                }
                increasing = true;
            }
        } else { /*--The sequence was increasing--*/
            if (current > old) { /*The sequence keeps increasing*/
                globalMax = max(current, globalMax);
                if (increasingCase(mins, maxs, lastMaxInserted, current)) {
                    printf("ELEGIR OTRA\n");
                    ignoreStuff(); /*Ignoring the rest*/
                    return true;
                }
            } else { /*The monotony changes*/
                if (current > globalMin) { /*Check if we can end*/
                    printf("ELEGIR OTRA\n");
                    ignoreStuff(); /*Ignoring the rest*/
                    return true;
                } else {
                    globalMin = current;
                    /*Inserting the local minimum (saved somewhere)*/
                    map<int, int>::iterator minIter;
                    minIter = mins.lower_bound(localMin);
                    if (!mins.empty() && minIter != mins.begin()) {
                        /*The value is the minimum position of the local
                         * minimums lower than the current local minimum*/
                        minIter--;
                        mins.insert(pair<int, int>(localMin, minIter->second));
                    } else {
                        mins.insert(pair<int, int>(localMin, localMinPos));
                    }
                    /*Inserting the local maximum (old)*/
                    /*The value is the maximum position of the local
                     * maximums greater or equal than than the current
                     * local maximum (i.e. the position of the local
                     * maximum). The local maximums lower than the
                     * current maximum have incoherent values, but it
                     * doesn't matter...*/
                    lastMaxInserted = maxs.insert(pair<int, int>(old, i - 1));
                    increasing = false;
                }
            }
        }
        old = current;
    }
    printf("SIEMPRE PREMIO\n");
    return true;
}

bool increasingCase(map<int, int> & mins, map<int, int> & maxs,
        pair<map<int, int>::iterator, bool> & lastMaxInserted,
        const int & current) {
    if (!mins.empty()) {
        /*--Getting the position of the first local minimum lower than current--*/
        map<int, int>::iterator minIter;
        minIter = mins.lower_bound(current);
        if (minIter != mins.begin()) {
            minIter--;
        } else {
            return false;
        }
        int minPos = minIter->second;
        /*--Trying to get a good local maximum coming after the minimum--*/
        if (!maxs.empty()) {
            map<int, int>::iterator maxIter;
            maxIter = maxs.upper_bound(current);
            if (maxIter != maxs.end()) {
                if (maxIter->first < lastMaxInserted.first->first) {
                    if (minPos > lastMaxInserted.first->second) {
                        return false;
                    }
                } else {
                    if (minPos > maxIter->second) {
                        return false;
                    }
                }
            } else {
                return false;
            }
        } else {
            return false;
        }
    } else {
        return false;
    }
    return true;
}

void ignoreStuff() {
    char trash = getchar();
    while (trash != '\n') {
        trash = getchar();
    }
}

Любая идея?

0 ответов

Другие вопросы по тегам