Pagini recente » Cod sursa (job #1517218) | Cod sursa (job #750595) | Cod sursa (job #52069) | Cod sursa (job #2218019) | Cod sursa (job #574159)
Cod sursa(job #574159)
#include<fstream>
#include<vector>
#include<iomanip>
using namespace std;
const int maxn = 100010;
const int maxm = 2000010;
vector <int> v[maxn];
int t[maxn], level[maxn];
int ap[2*maxn+10], euler[2*maxn+10], h[2*maxn+10];
int logarithm[2*maxn+10];
int min_block[2*maxn+10], pos_min_block[2*maxn+10], block_type[2*maxn+10];
int c[2*maxn+10][25];
int p[2*maxn+10][25][25], s[20];
int pos_max = 1, h_max = 1;
ofstream g("lca.out");
void eulerTour(int nod, int &i) {
i++;
euler[i] = nod;
h[i] = level[nod];
if (h[i] > h_max) {
h_max = h[i];
pos_max = i;
}
ap[nod] = i;
for (int j = 0; j < v[nod].size(); j++) {
level[v[nod][j]] = level[nod]+1;
eulerTour(v[nod][j], i);
i++;
euler[i] = nod;
h[i] = level[nod];
}
}
void buildTable(int size, int k, int &value) {
int actual, minim;
if (k == size+1) {
for (int i = 1; i <= size; i++) {
p[value][i][i] = i;
actual = s[i];
minim = s[i];
for (int j = i+1; j <= size; j++) {
p[value][i][j] = p[value][i][j-1];
actual = actual + s[j];
if (actual < minim) {
p[value][i][j] = j;
minim = actual;
}
}
}
}
else {
s[k] = -1;
value = value*2;
buildTable(size, k+1, value);
s[k] = 1;
value = value+1;
buildTable(size, k+1, value);
value--;
value = value/2;
}
}
int queryOnC(int x, int y) {
int length = y-x+1;
//g << "*" << x << " " << y << "* ";
int log_length = logarithm[length];
int res = c[x][log_length];
//g << " OnC " << res << " " << y-(1<<log_length)+1 << " ";
if (h[res] > h[c[y-(1<<log_length)+1][log_length]])
res = c[y-(1<<log_length)+1][log_length];
//g << " OnC " << res << " ";
return pos_min_block[res];
}
int queryOnP(int x, int y, int type) {
return p[type][x][y];
}
int query(int x, int y, int size) {
//g << x << " " << y << ": ";
int res, aux;
int left, right, block;
left = x%size;
if (left == 0)
left = size;
right = size;
block = (x-1)/size+1;
aux = queryOnP(left, right, block_type[block]);
res = (block-1)*size + aux;
//g << "1=> l = " << left << " r = " << right << " b = " << block << " res = " << res << "/ ";
left = (x-1)/size+1+1;
right = (y-1)/size;
if (left <= right) {
aux = queryOnC(left, right);
if (h[aux] < h[res])
res = aux;
}
//g << "2=> l = " << left << " r = " << right << " b = " << block << " res = " << res << "/ ";
left = 1;
right = y%size;
if (right == 0)
right = size;
block = (y-1)/size+1;
aux = queryOnP(left, right, block_type[block]);
aux = (block-1)*size + aux;
if (h[aux] < h[res])
res = aux;
//g << "3=> l = " << left << " r = " << right << " b = " << block << " res = " << res << "/ ";
return res;
}
int main() {
ifstream f("lca.in");
int n, m;
int x, y;
f >> n >> m;
t[1] = -1;
for (int i = 2; i <= n; i++) {
f >> x;
t[i] = x;
v[x].push_back(i);
}
level[1] = 1;
int nr = 0;
eulerTour(1, nr);
int total_size = 2*n-1;
logarithm[1] = 0;
x = 1; int next = 2;
for (int i = 2; i <= total_size; i++) {
logarithm[i] = logarithm[i-1];
if (i == next) {
logarithm[i]++;
next = next*2;
}
}
int one_block_size = logarithm[total_size]/2;
//g << one_block_size << endl;
int pos = 2, min_block_size = 1;
x = 2;
pos_min_block[1] = 1;
min_block[1] = h[1];
int value = 1, sign;
while (pos <= total_size) {
sign = h[pos] - h[pos-1];
if (x == one_block_size+1) {
block_type[min_block_size] = value;
min_block_size++;
pos_min_block[min_block_size] = pos;
min_block[min_block_size] = h[pos];
x = 2;
if (sign == -1)
value = 0;
else
value = 1;
}
else {
if (min_block[min_block_size] > h[pos]) {
pos_min_block[min_block_size] = pos;
min_block[min_block_size] = h[pos];
}
x++;
value = value*2;
if (sign == 1)
value++;
}
pos++;
}
//preprocesarea lui min_block
for (int i = 1; i <= min_block_size; i++)
c[i][0] = i;
for (int j = 1; (1<<j) <= min_block_size; j++) {
x = (1<<(j-1));
for (int i = 1; i+(1<<j)-1 <= min_block_size; i++) {
c[i][j] = c[i][j-1];
if (min_block[c[i+x][j-1]] < min_block[c[i][j]])
c[i][j] = c[i+x][j-1];
}
}
nr = 0;
buildTable(one_block_size, 1, nr);
int ax, ay, aux;
for (int i = 1; i <= m; i++) {
f >> x >> y;
ax = ap[x];
ay = ap[y];
if (ax > ay) {
aux = ax;
ax = ay;
ay = aux;
}
int res = query(ax, ay, one_block_size);
res = euler[res];
g << res << '\n';
}
return 0;
}