Pagini recente » Cod sursa (job #834616) | Cod sursa (job #3189049) | Diferente pentru implica-te/arhiva-educationala intre reviziile 223 si 2 | Cod sursa (job #2135633) | Cod sursa (job #1221433)
#include <fstream>
#include <cstdlib>
using namespace std;
const int N = 2e5, B = 4, LG = 18 - B;
class FastLCA{
int rmq[LG][N >> B];
int *bro, *son, *depth, *euler, *poz, *getBinBest, *bucket;
int size, mask;
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( best(x, y), z );
}
inline int getBest(int x, int y){
return euler[ x + getBinBest[ ( (bucket[x >> B] >> x) & ( (1 << (y - x) ) - 1 ) ) ^ ( 1 << (y - x) ) ] ];
}
inline int getRMQ(int x, int y){
int L = 31 - __builtin_clz(y - x + 1);
return best( rmq[L][x], rmq[L][y - (1 << L) + 1] );
}
void dfs(int x){
poz[x] = size;
euler[ size++ ] = x;
for (int y = son[x] ; y ; y = bro[y]){
depth[y] = 1 + depth[x];
dfs(y);
euler[ size++ ] = x;
}
}
public:
void buildTree(int T[], int n){
bro = (int*)calloc(n + 1, sizeof(int));
son = (int*)calloc(n + 1, sizeof(int));
poz = (int*)calloc(n + 1, sizeof(int));
depth = (int*)calloc(n + 1, sizeof(int));
euler = (int*)calloc(2 * n, sizeof(int));
size = 0;
for (int i = 2 ; i <= n ; i++){
bro[i] = son[ T[i] ];
son[ T[i] ] = i;
}
dfs(1);
free(bro);
free(son);
getBinBest = (int*)calloc(1 << (1 << B), sizeof(int));
bucket = (int*)calloc(1 + (N >> B), sizeof(int));
for (int i = 2 ; i < 1 << (1 << B) ; i++){
getBinBest[i] = 1 + getBinBest[i >> 1];
if ( (__builtin_popcount( i & ( (1 << getBinBest[i]) - 1 ) ) << 1 ) <= getBinBest[i] )
getBinBest[i] = 0;
}
mask = (1 << B) - 1;
for (int i = 0 ; i < size ; i++)
if ( i & mask )
bucket[i >> B] ^= ( depth[ euler[i] ] < depth[ euler[i - 1] ] ) << ( (i & mask) - 1);
for (int i = 0 ; i < (size >> B) ; i++)
rmq[0][i] = euler[ (i << B) ^ getBinBest[ bucket[i] ^ (1 << mask) ] ];
for (int i = 1, step = 1 ; i < LG ; i++)
for (int j = 0 ; j <= size ; j++)
rmq[i][j] = best(rmq[i - 1][j], rmq[i - 1][j + step]);
}
inline int lca(int x, int y){
x = poz[x]; y = poz[y];
if (x > y) swap(x, y);
if ( (x >> B) == (y >> B) )
return getBest(x, y);
return best( getBest(x, x | mask), getRMQ( 1 + (x >> B), (y >> B) - 1 ), getBest( (y >> B) << B, y ) );
}
};
FastLCA tree;
int T[N], n;
int main(){
ifstream in("lca.in");
ofstream out("lca.out");
int nrQ, x, y;
in >> n >> nrQ;
for (int i = 2 ; i <= n ; i++)
in >> T[i];
tree.buildTree(T, n);
while (nrQ--){
in >> x >> y;
out << tree.lca(x, y) << '\n';
}
out.close();
in.close();
return 0;
}