Cod sursa(job #1559929)

Utilizator tudorcomanTudor Coman tudorcoman Data 31 decembrie 2015 20:15:20
Problema Lowest Common Ancestor Scor 60
Compilator cpp Status done
Runda Arhiva educationala Marime 4.13 kb
#include <cstdio>
#include <cstring>
#include <vector>
#include <cctype>
#include <algorithm>

using namespace std;

const int maxN = 100000;
const int maxNd = maxN << 1;
const int maxSize = 1 << 20;

class ReadStream {
private:
  int cursor;
  char buf[maxSize];
  FILE *f;
  inline void move() {
    ++ cursor;
    if(cursor == maxSize) {
      cursor = 0;
      fread(buf, maxSize, 1, f);
    }
  }
  inline int todig(char c) {
    return c - '0';
  }
  
public:
  ReadStream() {}
  ReadStream(const char *fname) {
    f = fopen(fname, "r");
    cursor = 0;
    fread(buf, maxSize, 1, f);
  }
  
  ReadStream &operator >> (int& N) {
    char sign = '+';
    while(!isdigit(buf[cursor])) {
      sign = buf[cursor];
      move();
    }
    
    N = 0;
    while(isdigit(buf[cursor])) {
      N = N * 10 + todig(buf[cursor]);
      move();
    }
    
    if(sign == '-')
      N = -N;
    return *this;
  }
  
  ReadStream &operator >> (float& N) {
    char sign = '+';
    while(!isdigit(buf[cursor])) {
      sign = buf[cursor];
      move();
    }
    N = 0;
    while(isdigit(buf[cursor])) {
      N = N * 10 + todig(buf[cursor]);
      move();
    }
    
    if(buf[cursor] == '.') {
      float p = 0.1;
      move();
      while(isdigit(buf[cursor])) {
        N = N + p * todig(buf[cursor]);
        p *= 0.1;
        move();
      }
    }
    
    if(sign == '-')
      N = -N;
    return *this;
  }
};

class WriteStream {
private:
  FILE* stream;
  
  int pos;
  char buffer[maxSize];
  
  void dump() {
    if (pos > maxSize) {
      fwrite(buffer, sizeof(char), pos, stream);
      pos = 0;
    }
  }
  
public:
  WriteStream(FILE* stream) {
    this->stream = stream;
    this->pos = 0;
  }
  
  WriteStream(const char *fname) {
    this->stream = fopen(fname, "w");
    this->pos = 0;
    memset(this->buffer, 0, sizeof buffer);
  }
  
  WriteStream& operator << (unsigned int value) {
    if (value == 0) {
      buffer[pos] = '0';
      pos++;
    } else {
      int newPos = pos;
      while(value > 0) {
        buffer[newPos] = '0' + (value % 10);
        newPos++;
        value /= 10;
      }
      std::reverse(buffer + pos, buffer + newPos);
      pos = newPos;
    }
    dump();
    return *this;
  }
  
  WriteStream& operator << (char value) {
    buffer[pos] = value;
    pos++;
    dump();
    return *this;
  }
  
  WriteStream& operator << (int value) {
    if(value == 0) {
      buffer[pos ++] = '0';
      dump();
      return *this;
    }
    if(value < 0)
      buffer[pos ++] = '-', value = -value;
    
    int newPos = pos;
    while(value > 0) {
      buffer[newPos ++] = '0' + (value % 10);
      value /= 10;
    }
    
    std::reverse(buffer + pos, buffer + newPos);
    pos = newPos;
    dump();
    return *this;
  }
  
  ~WriteStream() {
    fwrite(buffer, sizeof(char), pos, stream);
  }
  
};

int N;
bool viz[1 + maxN];
vector<int> sons[1 + maxN];

int id[1 + maxN], ac;
int euler[maxNd], where[1 + maxN], e;

int rmq[20][maxNd << 1];
int Log[maxNd + 1];

void rmqCompute(int v[], int N) {
  for(int i = 0; i < N; ++ i)
    rmq[0][i] = v[i];
  for(int i = 1; (1 << i) <= N; ++ i)
    Log[(1 << i)] = 1;
  for(int i = 1; i <= N; ++ i)
    Log[i] += Log[i - 1];
  
  int p = 2;
  for(int step = 1; p <= N; ++ step, p <<= 1) {
    int put = p >> 1;
    for(int i = 0; i + put < N; ++ i)
      rmq[step][i] = min(rmq[step - 1][i], rmq[step - 1][i + put]);
  }
}

int rmQuery(int x, int y) {
  int l = y - x + 1;
  int step = Log[l];
  return min(rmq[step][x], rmq[step][y - (1 << step) + 1]);
}


void dfs(int node = 1) {
  if(!viz[node]) {
    viz[node] = true;
    int nodeAc = ac;
    id[ac ++] = node;
    where[node] = e;
    euler[e ++] = nodeAc;
    for (int son: sons[node]) {
      dfs(son);
      euler[e ++] = nodeAc;
    }
  }
}

int lca(int x, int y) {
  x = where[x];
  y = where[y];
  return id[rmQuery(min(x, y), max(x, y))];
}

int main() {
  ReadStream in("lca.in");
  WriteStream out("lca.out");
  int M;
  in >> N >> M;
  for(int i = 2; i <= N; ++ i) {
    int fatherI;
    in >> fatherI;
    sons[fatherI].push_back(i);
  }
  
  dfs();
  rmqCompute(euler, e);
  
  while(M --) {
    int x, y;
    in >> x >> y;
    out << lca(x, y) << '\n';
  }
  
  return 0;
}