Cod sursa(job #1982419)

Utilizator BogdanisarBurcea Bogdan Madalin Bogdanisar Data 18 mai 2017 19:13:41
Problema Statistici de ordine Scor 60
Compilator cpp Status done
Runda Arhiva educationala Marime 3.3 kb
#include <iostream>
#include <fstream>
#include <algorithm>

using namespace std;
ifstream in("sdo.in");
ofstream out("sdo.out");

#define ll long long
#define pb push_back
const int NMax = 3e6 + 5;

// solutie O(n + klogk)

int N,K,nrHeap;
int v[NMax],heap[NMax];
// v = vectorul initial, care va fi organizat intr-o structura de heap
// heap = un heap ce retine valoarea minima si compara doua elemente heap[i],heap[j]
//        folosind valoarea lor din vectorul v (ex.: v[heap[i]] < v[heap[j]]),
//        heap[i] reprezentand indexul unui element din v

void siftFirst(int,int);
// siftFirst(i,dim) muta nodul i in jos pana la pozitia corespunzatoare in vectorul v,
//                  care are dim elemente
void siftSecond(int,int);
// siftSecond(i,dim) muta nodul i in jos pana la pozitia corespunzatoare in vectorul heap,
//                   care are dim elemente
void percolate(int);
// percolate(i) muta nodul i in sus pana la pozitia corespunzatoare in vectorul heap,
//                   care are dim elemenete

int main() {
    in>>N>>K;
    for (int i=1;i <= N;++i) {
        in>>v[i];
    }

    // buildHeap
    // se transforma v intr-o structura de heap
    for (int i=N/2;i > 0;--i) {
        siftFirst(i,N);
    }

    // se introduce elementul minim din v (v[1]) in heap,
    // iar la fiecare iteratie se gaseste urmatorul element minim din v
    // si se introduc fii acestui minim in heap
    // pentru ca ele reprezinta un posibil urmator minim
    heap[++nrHeap] = 1;
    for (int c=1;c < K;++c) {
        int node = heap[1];

        swap(heap[1],heap[nrHeap]);
        --nrHeap;
        siftSecond(1,nrHeap);
        // acest minim este scos doarece nu ne intereseaza primele K-1 minime

        // se introduc fii
        int fs = node*2,ss = fs+1;
        if (fs <= N) {
            heap[++nrHeap] = fs;
            percolate(nrHeap);
        }
        if (ss <= N) {
            heap[++nrHeap] = ss;
            percolate(nrHeap);
        }
    }

    // acum, heap[1] va fi a K-a valoare minima din v
    out<<v[heap[1]]<<'\n';

    in.close();out.close();
    return 0;
}

void siftFirst(int node,int dim) {

    int son = 0;
    do {
        son = 0;
        int fs = node*2,
            ss = node*2 + 1;
        if (fs <= dim) {
            son = fs;
            if (ss <= dim && v[ss] < v[son]) {
                son = ss;
            }
        }

        if (son && v[son] < v[node]) {
            swap(v[node],v[son]);
            node = son;
        }
        else {
            son = 0;
        }
    }
    while (son);
}

void siftSecond(int node,int dim) {

    int son = 0;
    do {
        son = 0;
        int fs = node*2,
            ss = node*2 + 1;
        if (fs <= dim) {
            son = fs;
            if (ss <= dim && v[heap[ss]] < v[heap[son]]) {
                son = ss;
            }
        }

        if (son && v[heap[son]] < v[heap[node]]) {
            swap(heap[node],heap[son]);
            node = son;
        }
        else {
            son = 0;
        }
    }
    while (son);
}

void percolate(int node) {

    int dad = node/2;
    while (node != 1 && v[heap[node]] < v[heap[dad]]) {
        swap(heap[node],heap[dad]);
        node = dad;

        dad = node/2;
    }
}