给定n个非重复整数列表L:=(x1,...,xn)开发一个算法,确定L中是否有xi1,xi2,xi3使得i1低于i2,i2低于比i_3,xi1低于xi3,xi3低于xi2。只需要是 - 否答案。
该声明还建议使用“分而治之”策略。
我的尝试如下:
我从左到右阅读了矢量
所以复杂性是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", ¤t);
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", ¤t); /*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();
}
}
有什么想法吗?