找到(小 - 大 - 中)子序列

时间:2018-03-17 20:24:17

标签: c++ divide-and-conquer

  

给定n个非重复整数列表L:=(x1,...,xn)开发一个算法,确定L中是否有xi1,xi2,xi3使得i1低于i2,i2低于比i_3,xi1低于xi3,xi3低于xi2。只需要是 - 否答案。

该声明还建议使用“分而治之”策略。

我的尝试如下:

我从左到右阅读了矢量

  • 如果列表从增加变为减少,则很明显最后读取的数字低于当前读取列表的最大值。因此,如果它大于当前列表的最小值,我们就可以停止。
  • 如果列表从减少变为增加,那么我查找列表中的第一个数字m是局部最小值并且它低于最后读取的数字c。然后我寻找一个局部最大值出现在m之后,大于c。
  • 如果列表不断增加,我们会像上一步一样。
  • 如果列表不断减少则不做任何事。

所以复杂性是nlogn。我认为策略是好的,但在线评委拒绝了。我不知道这是由于一个愚蠢的错误还是因为策略确实是错误的。

#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 个答案:

没有答案