Pagini recente » Cod sursa (job #194020) | Cod sursa (job #2644946) | Cod sursa (job #2986576) | Cod sursa (job #2631740) | Cod sursa (job #1189813)
#include <fstream>
#include <vector>
using namespace std;
const int N = 1 + 1e5, inf = 0x3f3f3f3f;
const int LG = 17, Bucket = 4;
const int Size = 1 + 2 * N / Bucket;
int rmq[LG][Size], bucketMask[Size], bucketQuery[1 << Bucket][Bucket][Bucket];
int T[N], depth[N], euler[2 * N + 2 * Bucket], start[N], timp, n;
vector<int> tree[N];
void dfs(int x){
start[x] = timp;
euler[ timp++ ] = x;
for (auto it = tree[x].begin() ; it != tree[x].end() ; it++)
if (depth[*it] == 0){
depth[*it] = 1 + depth[x];
dfs(*it);
euler[ timp++ ] = x;
}
}
inline int best(int x, int y){
return depth[x] < depth[y] ? x : y;
}
inline int best(int x, int y, int z){
return best( x, best(y, z) );
}
inline int rmqQuery(int st, int dr){
if (dr < st)
return 0;
int L = 31 - __builtin_clz(dr - st + 1);
return best( rmq[L][st], rmq[L][dr - (1 << L) + 1] );
}
inline int leftQuery(int x){
return euler[ x - x % Bucket + bucketQuery[ bucketMask[ x / Bucket ] ][0][x % Bucket] ];
}
inline int rightQuery(int x){
return euler[ x - x % Bucket + bucketQuery[ bucketMask[ x / Bucket ] ][x % Bucket][Bucket - 1] ];
}
inline int midQuery(int x, int y){
return euler[ x - x % Bucket + bucketQuery[ bucketMask[ x / Bucket ] ][x % Bucket][y % Bucket] ];
}
int lca(int x, int y){
x = start[x];
y = start[y];
if (x > y) swap(x, y);
if (x / Bucket == y / Bucket)
return midQuery(x, y);
return best( rightQuery(x), rmqQuery(x / Bucket + 1, y / Bucket - 1), leftQuery(y) );
}
inline int getDepth(int mask, int poz){
return poz - 2 * __builtin_popcount( mask >> (Bucket - poz - 1) );
}
int getMask(int st, int dr){
int ans = 0, last = 0;
for (int i = st ; i < dr ; i++){
ans = (ans << 1) ^ ( depth[ euler[i] ] < last );
last = depth[ euler[i] ];
}
return ans;
}
void compute(){
depth[0] = inf;
depth[1] = 1;
dfs(1);
for (int i = 0 ; i < (1 << Bucket) ; i++)
for (int st = 0 ; st < Bucket ; st++){
bucketQuery[i][st][st] = st;
for (int dr = st + 1 ; dr < Bucket ; dr++)
if ( getDepth(i, bucketQuery[i][st][dr - 1]) < getDepth(i, dr) )
bucketQuery[i][st][dr] = bucketQuery[i][st][dr - 1];
else
bucketQuery[i][st][dr] = dr;
}
int size = 1 + 2 * n / Bucket;
for (int i = 0 ; i <= size ; i++){
bucketMask[i] = getMask( i * Bucket, (i + 1) * Bucket );
rmq[0][i] = euler[ i * Bucket + bucketQuery[ bucketMask[i] ][0][Bucket - 1] ];
}
for (int i = 1, step = 1 ; i < LG ; i++, step <<= 1)
for (int j = 0 ; j + step <= size ; j++)
rmq[i][j] = best( rmq[i - 1][j], rmq[i - 1][j + step] );
}
int main(){
int nrQ, x, y;
ifstream in("lca.in");
in >> n >> nrQ;
for (int i = 2 ; i <= n ; i++){
in >> T[i];
tree[ T[i] ].push_back(i);
}
compute();
ofstream out("lca.out");
while (nrQ--){
in >> x >> y;
out << lca(x, y) << '\n';
}
in.close();
out.close();
return 0;
}