Cod sursa(job #2397907)

Utilizator Kln1000Ciobanu Bogdan Kln1000 Data 4 aprilie 2019 21:17:15
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.45 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <cmath>

using namespace std;

class parser{
    public:
        parser() {}
        parser(const char *file_name){
            input_file.open(file_name,ios::in | ios::binary);
            input_file.sync_with_stdio(false);
            index=0;
            input_file.read(buffer,SIZE);}
        inline parser &operator >>(int &n) {
            for (;buffer[index]<'0' or buffer[index] > '9'; inc());
            n &= 0;
            for (; buffer[index] >= '0' and buffer[index] <= '9'; inc())
                n = (n << 3) + (n << 1) + buffer[index] - '0';
            return *this;
        }
        inline parser &operator >>(char n[]){
            for (;buffer[index]<'0' or buffer[index]>'z';inc());
            int it=0;
            for (;'0'<=buffer[index] and buffer[index]<='z';inc())
                n[it++]=buffer[index];
            n[it]='\0';
            return *this;}
        ~parser(){
            input_file.close();}
    private:
        fstream input_file;
        static const int SIZE=0x400000;
        char buffer[SIZE];
        int index=0;
        inline void inc(){
            if(++index==SIZE)
                index=0,input_file.read(buffer,SIZE);}
};

class writer{
    public:
        writer() {};
        writer(const char *file_name){
            output_file.open(file_name,ios::out | ios::binary);
            output_file.sync_with_stdio(false);
            index&=0;}
        inline writer &operator <<(int target){
            aux&=0;
            n=target;
            if (!n)
                nr[aux++]='0';
            for (;n;n/=10)
                nr[aux++]=n%10+'0';
            for(;aux;inc())
                buffer[index]=nr[--aux];
            return *this;}
        inline writer &operator <<(const char *target){
            aux&=0;
            while (target[aux])
                buffer[index]=target[aux++],inc();
            return *this;}
        ~writer(){
            output_file.write(buffer,index);output_file.close();}
    private:
        fstream output_file;
        static const int SIZE=0x200000; ///2MB
        int index,aux,n;
        char buffer[SIZE],nr[24];
        inline void inc(){
            if(++index==SIZE)
                index&=0,output_file.write(buffer,SIZE);}
};

parser f("lca.in");
writer t("lca.out");


using namespace std;
/*
ifstream f ("lca.in");
ofstream t ("lca.out");
*/
vector <int> groups;
int n, m, depth[100010], grup[100010], tata[100010];

void preprocess() {
    int bucket_size = sqrt(n / 2);

    for (int i = 1; i <= n; ++i) {
        if (depth[i] % bucket_size == 0) {
            groups.push_back(tata[i]);
            grup[i] = groups.size() - 1;
        } else {
            grup[i] = grup[tata[i]];
        }
    }
}

int H_BFS(int x, int y) {
    while (x != y)
        if (depth[x] > depth[y])
            x = tata[x];
        else
            y = tata[y];
    return x;
}

int lca(int x, int y) {
    while (grup[x] != grup[y])
        if (depth[x] > depth[y])
            x = groups[grup[x]];
        else
            y = groups[grup[y]];

    return H_BFS(x, y);
}

int main()
{
    f >> n >> m;
    for (int x, i = 2; i <= n; ++i)
        f >> x,
        tata[i] = x,
        depth[i] = depth[x] + 1;
    preprocess();
    for (int x, y, i = 0; i < m; ++i)
        f >> x >> y,
        t << lca(x, y) << "\n";
    return 0;
}