Cod sursa(job #2082546)

Utilizator andreiiiiPopa Andrei andreiiii Data 6 decembrie 2017 15:38:15
Problema Sortare Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.7 kb
#include <algorithm>
#include <fstream>
#include <cstdlib>
#include <random>
#include <iostream>
#include <cassert>
#include <vector>
#define SZ(x) ((int) (x).size())
using namespace std;

struct ChooseMethod {
    int a, b, c;
};

int qsort(const vector<ChooseMethod>& v, const vector<int>& values) {
    vector<int> left, right;
    if (SZ(values) <= 1) {
        return 1;
    }
    int n = SZ(values);
    int pivot = max({values[v[n].a], values[v[n].b], values[v[n].c]}) ^
                min({values[v[n].a], values[v[n].b], values[v[n].c]}) ^
                values[v[n].a] ^ values[v[n].b] ^ values[v[n].c];
    for (int x: values) {
        if (x < pivot) {
            left.push_back(x);
        } else if (x > pivot) {
            right.push_back(x);
        }
    }
    return 1 + max(qsort(v, left), qsort(v, right));
}

void fastRemove(vector<int>& a, int pos) {
    memmove(a.data() + pos, a.data() + pos + 1, sizeof(int) * (SZ(a) - pos - 1));
    a.resize(SZ(a) - 1);
}

int choose(vector<int>& values, const vector<ChooseMethod>& v,
            vector<int>& rem, int val) {
    if (val == 0) {
        values[rem[0]] = val;
        rem.pop_back();
        return 0;
    }
    int len = val + 1;
    ChooseMethod curr = v[len];
    if (curr.a != curr.b && curr.b != curr.c && curr.c != curr.a) {
        values[rem[curr.a]] = val;
        values[rem[curr.b]] = val - 1;
        fastRemove(rem, curr.a);
        if (curr.b > curr.a) {
            curr.b--;
        }
        fastRemove(rem, curr.b);
        return 1 + choose(values, v, rem, val - 2);
    } else if (curr.a == curr.b || curr.a == curr.c) {
        values[rem[curr.a]] = val;
        fastRemove(rem, curr.a);
        return choose(values, v, rem, val - 1);
    } else {
        values[rem[curr.b]] = val;
        fastRemove(rem, curr.b);
        return choose(values, v, rem, val - 1);
    }
}

pair<vector<int>, int> solve(const vector<ChooseMethod>& v) {
    int n = SZ(v) - 1;
    vector<int> rem;
    for (int i = 0; i < n; ++i) {
        rem.push_back(i);
    }
    vector<int> values(n, -1);
    int sub = choose(values, v, rem, n - 1);

    // if (find(values.begin(), values.end(), -1) != values.end()) {
    //     throw 1;
    // }
    // if (qsort(v, values) != n - sub) {
    //     throw 2;
    // }
    return make_pair(values, sub);
}

class Random {
public:
    Random(int seed):
        rnd(seed) {}

    int nextInt(int n) {
        int res = rnd() % n;
        if (res < 0) {
            res += n;
        }
        return res;
    }
private:
    mt19937 rnd;
};

void genRandomTestcases() {
    Random rnd(time(0));
    for (int t = 1; ; ++t) {
        int n = rnd.nextInt(5000) + 10;
        vector<ChooseMethod> v(n + 1);
        for (int len = 2; len <= n; ++len) {
            int a = rnd.nextInt(len);
            int b = rnd.nextInt(len);
            int c = rnd.nextInt(len);
            v[len] = ChooseMethod{a, b, c};
        }
        try {
            solve(v);
        } catch (int) {
            cerr << "Wrong on: " << endl;
            cerr << n << endl;
            for (int i = 2; i <= n; ++i) {
                cerr << v[i].a << ' ' << v[i].b << ' ' << v[i].c << endl;
            }
            return;
        }
        cerr << "Done on test #" << t << "!" << endl;
    }
}

int main() {
    ifstream fin("sortare.in");
    ofstream fout("sortare.out");

    int n;
    fin >> n;

    vector<ChooseMethod> v(n + 1);
    for (int i = 2; i <= n; ++i) {
        fin >> v[i].a >> v[i].b >> v[i].c;
        v[i].a--;
        v[i].b--;
        v[i].c--;
    }
    int sub;
    vector<int> values;
    tie(values, sub) = solve(v);
    fout << n - sub << '\n';
    for (int x: values) {
        fout << x + 1 << ' ';
    }
    fout << '\n';

    fin.close();
    fout.close();
}