Cod sursa(job #1569333)

Utilizator usermeBogdan Cretu userme Data 15 ianuarie 2016 12:57:31
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.26 kb
#include <stdio.h>
#include <assert.h>
#include <vector>
#include <queue>

template<int SIZE>
class ReadStream {
private:
    FILE* stream;

    int pos;
    char buffer[SIZE + 1];

public:
    ReadStream(FILE* stream) {
        this->stream = stream;
        this->pos = SIZE;
    }

    int nextInt() {
        int answer = 0;
        int readSize;

        while (true) {
            if (this->pos == SIZE) {
                readSize = fread(this->buffer, sizeof(char), SIZE, this->stream);
                this->buffer[readSize] = 0;
                this->pos = 0;
            }
            if ('0' <= this->buffer[this->pos] && this->buffer[this->pos] <= '9') {
                break;
            } else {
                ++this->pos;
            }
        }
        while (true) {
            if (this->pos == SIZE) {
                readSize = fread(this->buffer, sizeof(char), SIZE, this->stream);
                this->buffer[readSize] = 0;
                this->pos = 0;
            }
            if (!('0' <= this->buffer[this->pos] && this->buffer[this->pos] <= '9')) {
                break;
            } else {
                answer *= 10;
                answer += this->buffer[this->pos] - '0';
                ++this->pos;
            }
        }

        return answer;
    }

    char nextChar() {
        int readSize;
    if (this->pos == SIZE) {
      readSize = fread(this->buffer, sizeof(char), SIZE, this->stream);
      this->buffer[readSize] = 0;
      this->pos = 0;
    }
    return this->buffer[this->pos++];
    }
};


using std::vector;
using std::queue;

const int MAX_N = 100000;
const int LOG_MAX_N = 17;

int N, M;

vector<int> sons[1 + MAX_N];

int power[(1 << LOG_MAX_N) + 1];

int depth[1 + MAX_N];
int father[1 + LOG_MAX_N][1 + MAX_N];

queue<int> bfsQ;

void climb(int &node, int level) {
  while (level > 0) {
    node = father[power[level & (-level)]][node];
    level &= level - 1;
  }
}

ReadStream<1000000> read(stdin);

int main() {
  int i, j;
  freopen("lca.in", "r", stdin);
  freopen("lca.out", "w", stdout);
  //scanf("%d %d", &N, &M);
  N = read.nextInt();
  M = read.nextInt();
  for (i = 2; i <= N; i++) {
    //scanf("%d", &father[0][i]);
    father[0][i] = read.nextInt();
    sons[father[0][i]].push_back(i);
  }
  for (i = 1; i <= LOG_MAX_N; i++) {
    for (j = 1; j <= N; j++) {
      father[i][j] = father[i - 1][father[i - 1][j]];
    }
  }
  bfsQ.push(1);
  depth[1] = 1;
  while (!bfsQ.empty()) {
    int node = bfsQ.front();
    bfsQ.pop();
    for(int son : sons[node]) {
      bfsQ.push(son);
      depth[son] = depth[node] + 1;
    }
  }

  for (i = 0; i <= LOG_MAX_N; i++) {
    power[1 << i] = i;
  }
  for (i = 0; i <= N; i++) {
    if (power[i] == 0) {
      power[i] = power[i - 1];
    }
  }

  for (i = 1; i <= M; i++) {
    int a, b;
    int lca;
    //scanf("%d %d", &a, &b);
    a = read.nextInt();
    b = read.nextInt();

    int dif = depth[a] - depth[b];
    if (dif < 0) {
      climb(b, -dif);
    } else {
      climb(a, dif);
    }
    assert(depth[a] == depth[b]);

    if (a == b) {
      lca = a;
    } else {
      for (j = power[depth[a]]; j >= 0; j--) {
        if (father[j][a] != father[j][b]) {
          a = father[j][a];
          b = father[j][b];
        }
      }
      lca = father[0][a];
    }

    printf("%d\n", lca);
  }
  return 0;
}