Cod sursa(job #951118)

Utilizator mihai995mihai995 mihai995 Data 19 mai 2013 12:43:33
Problema Statistici de ordine Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.17 kb
#include <fstream>
#include <ctime>
#include <cstdlib>
using namespace std;

#define QUICK 1

inline bool maiMic(int a, int b) {
    return a < b;
}

inline bool maiMare(int a, int b) {
    return a > b;
}

void cleanup(int v[], int& n, int p, bool(*op)(int, int)) {
    v[0] = 0;
    for (int i = 1 ; i <= n ; i++)
        if (op(v[i], p))
            v[++v[0]] = v[i];
    n = v[0];
}

int rang(int v[], int n, int p) {
    int nr = 0;

    for (int i = 1 ; i <= n ; i++)
        if (v[i] <= p)
            ++nr;

    return nr;
}

int best(int v[], int n, bool(*op)(int, int)) {
    int rez = v[1];

    for (int i = 2 ; i <= n ; i++)
        if (op(v[i], rez))
            rez = v[i];

    return rez;
}

int sdoQuick(int v[], int n, int k) {
    srand(time(NULL));

    while (k != 1 && k != n) {
        int p = v[1 + rand() % n], nr;
        nr = rang(v, n, p);

        if (nr == k)
            return p;

        if (nr < k) {
            k -= nr;
            cleanup(v, n, p, maiMare);
        } else
            cleanup(v, n, p, maiMic);
    }

    if (k == 1)
        return best(v, n, maiMic);
    return best(v, n, maiMare);
}

int sdoBS(int v[], int n, int k){
    int rez, step, Q;

    rez = best(v, n, maiMic);
    Q = best(v, n, maiMare) - rez;

    for (step = 1 ; step <= Q ; step <<= 1);
    step >>= 1;

    for ( ; step && k != 1 && k != n ; step >>= 1){
        Q = rang(v, n, rez + step);

        if (k == Q){
            cleanup(v, n, rez + step + 1, maiMic);
            return best(v, n, maiMare);
        }

        if (Q < k){
            k -= Q;
            rez += step;
            cleanup(v, n, rez, maiMare);
        } else
            cleanup(v, n, rez + step, maiMic);
    }

    if (k == 1)
        return best(v, n, maiMic);
    return best(v, n, maiMare);
}

const int N = 1 + 3e6;

int v[N], n;

ifstream in("sdo.in");
ofstream out("sdo.out");

int main(){
    int k;

    in >> n >> k;

    for (int i = 1 ; i <= n ; i++)
        in >> v[i];

    if (QUICK)
        out << sdoQuick(v, n, k) << "\n";
    else
        out << sdoBS(v, n, k) << "\n";

    return 0;
}