Te dejo mi código AC y abajo explico la idea:
spoiler#include <bits/stdc++.h>
using namespace std;
typedef vector<int> vi;
typedef set<int> si;
typedef set<int, greater<int> > rsi;
int main() {
ios_base::sync_with_stdio(false); cin.tie(0);
int n;
while(cin >> n) {
vi v(n);
si already;
rsi future;
for(int& x : v) {
cin >> x;
future.insert(x);
}
bool ok = true;
future.erase(v[0]);
already.insert(v[0]);
for(int i=1; i<n-1 && ok; ++i) {
future.erase(v[i]);
int lowest = *already.begin();
int highest = future.lower_bound(v[i]) == future.end() ? -1 : *future.lower_bound(v[i]);
ok &= !(lowest < v[i] && v[i] > highest && lowest < highest);
already.insert(v[i]);
}
cout << (ok ? "SIEMPRE PREMIO" : "ELEGIR OTRA") << endl;
}
}
Otra versión#pragma GCC push_options
#pragma GCC optimize ("O2")
#include <cstdio>
#include <set>
#include <iostream>
using namespace std;
typedef set<int, greater<int> > rsi;
int v[500009];
int main() {
ios_base::sync_with_stdio(false);
int n;
while( scanf("%d", &n) == 1) {
rsi future;
for(int i = 0; i<n; ++i) {
scanf("%d", &v[i]);
future.insert(v[i]);
}
bool ok = true;
future.erase(v[0]);
int minv = v[0];
for(int i=1; i<n-1 && ok; ++i) {
future.erase(v[i]);
int lowest = minv;
auto x = future.lower_bound(v[i]);
int highest = x == future.end() ? -1 : *x;
ok &= !(lowest < v[i] && v[i] > highest && lowest < highest);
minv = min(minv, v[i]);
}
printf("%s", ok ? "SIEMPRE PREMIO\n" : "ELEGIR OTRA\n");
}
}
Básicamente, mantén dos sets de números con los números que ya has visto y los que te quedan por ver. Si el menor de los números que ya has visto es menor al máximo de los que te quedan por ver que a la vez sea menor a tu elemento actual entonces tienes un caso sin premio. Es decir:
- v(i) = Elemento que estamos tratando
- lowest = El elemento más pequeño del conjunto de números que ya hemos visto
- highest = El número más grande x del conjunto de números que estan por ver que satisface x < v(i)
Si lowest < v(i), v(i) > highest y lowest < highest para algún i en [1, n-2] (contando desde el cero), entonces mínimo un triplete sin premio.
Obtener el menor de un set es O(1) y el máximo que puedes usar sin pasarte del elemento actual es O(logn) si por ejemplo usas lower_bound (C++) o floor/ceiling (Java, TreeSet)
En Java puedes usar TreeSet y las funciones floor y ceiling para hacer lo mismo que he hecho yo. Con todo esto, la complejidad debería salirte O(n log n). Si tuviera el intellij con el chelper te lo haría también en Java, pero formateé hace poco
Por cierto, alguien de aquí está participando en la Facebook Hacker Cup?