Pagini recente » Cod sursa (job #3361629) | Cod sursa (job #3361463) | Cod sursa (job #3361483) | Cod sursa (job #3361322) | Cod sursa (job #3361489)
#include <fstream>
#include <vector>
using namespace std;
ifstream f("lca.in");
ofstream g("lca.out");
const int MAX_N = 100000,
MAX_BLOCK_SIZE = 8,
MAX_BLOCK_COUNT = ((MAX_N << 1) + MAX_BLOCK_SIZE - 1) / MAX_BLOCK_SIZE,
MAX_LOG2 = 14; /// log2(MAX_BLOCK_COUNT)
inline int max(int x, int y)
{
return (x > y) ? x : y;
}
struct Tree
{
vector<int> adj[MAX_N + 1];
int euler[MAX_N << 1],
depth[MAX_N + 1],
pos[MAX_N + 1];
int n, q, timer;
vector<vector<int>> blocks[1 << (MAX_BLOCK_SIZE - 1)];
int blockMask[MAX_BLOCK_COUNT];
int st[MAX_LOG2 + 1][MAX_N << 1],
log2[MAX_N << 1];
int m, blockSize, blockCount;
inline int Combine(int x, int y)
{
return (depth[euler[x]] < depth[euler[y]]) ? x : y;
}
void Read()
{
f >> n >> q;
for(int y = 2; y <= n; y++)
{
int x;
f >> x;
adj[x].push_back(y);
}
}
void DFS(int node, int dist = 0)
{
++timer;
euler[timer] = node;
depth[node] = dist;
pos[node] = timer;
for(int child : adj[node])
{
DFS(child, dist + 1);
++timer;
euler[timer] = node;
}
}
void EulerTour()
{
timer = -1;
DFS(1);
}
void FarachColtonBender()
{
m = timer + 1;
log2[1] = 0;
for(int i = 2; i <= m; i++)
log2[i] = log2[i >> 1] + 1;
blockSize = max(1, (log2[m] >> 1));
blockCount = (m + blockSize - 1) / blockSize;
for(int i = 0, pos = 0, blockIdx = 0; i < m; i++, pos++)
{
if(pos == blockSize)
{
pos = 0;
blockIdx++;
}
if(pos == 0 || Combine(i, st[0][blockIdx]) == i)
st[0][blockIdx] = i;
if(pos > 0 && Combine(i - 1, i) == i - 1)
blockMask[blockIdx] |= 1 << (pos - 1);
}
for(int p = 1; p <= log2[blockCount]; p++)
for(int i = 0; i < blockCount; i++)
{
if(i + (1 << (p - 1)) >= blockCount)
st[p][i] = st[p - 1][i];
else
st[p][i] = Combine(st[p - 1][i], st[p - 1][i + (1 << (p - 1))]);
}
for(int blockIdx = 0; blockIdx < blockCount; blockIdx++)
{
int mask = blockMask[blockIdx];
if(!blocks[mask].empty())
continue;
blocks[mask] = vector<vector<int>>(blockSize, vector<int>(blockSize));
for(int i = 0; i < blockSize; i++)
{
blocks[mask][i][i] = i;
for(int j = i + 1; j < blockSize; j++)
{
blocks[mask][i][j] = blocks[mask][i][j - 1];
if(blockIdx * blockSize + j < m)
{
blocks[mask][i][j] = Combine(blockIdx * blockSize + j,
blockIdx * blockSize + blocks[mask][i][j]);
blocks[mask][i][j] -= blockIdx * blockSize;
}
}
}
}
}
inline int BlockIdx(int blockIdx, int left, int right)
{
return blocks[blockMask[blockIdx]][left][right] + blockIdx * blockSize;
}
int LCA(int x, int y)
{
int left = pos[x],
right = pos[y];
if(left > right)
swap(left, right);
int blockLeft = left / blockSize,
blockRight = right / blockSize;
int idx = -1;
if(blockLeft == blockRight)
idx = BlockIdx(blockLeft, left % blockSize, right % blockSize);
else
{
idx = Combine(BlockIdx(blockLeft, left % blockSize, blockSize - 1),
BlockIdx(blockRight, 0, right % blockSize));
++blockLeft;
--blockRight;
int len = blockRight - blockLeft + 1;
if(len)
{
len = log2[len];
idx = Combine(idx, st[len][blockLeft]);
idx = Combine(idx, st[len][blockRight - (1 << len) + 1]);
}
}
return euler[idx];
}
void Solve()
{
while(q--)
{
int x, y;
f >> x >> y;
g << LCA(x, y) << '\n';
}
}
};
Tree tree;
int main()
{
tree.Read();
tree.EulerTour();
tree.FarachColtonBender();
tree.Solve();
f.close();
g.close();
return 0;
}