Pagini recente » Cod sursa (job #2463784) | Cod sursa (job #157090) | Cod sursa (job #3283364) | Cod sursa (job #1155092) | Cod sursa (job #2069764)
#include<bits/stdc++.h>
#include<iostream>
#include<fstream>
#include<cassert>
#include<cmath>
using namespace std;
ifstream in("lca.in");
ofstream out("lca.out");
const int N = 100000;
const int NLOG = 17 + 1; /// +1 Because we want to include level 0 too!
void array_to_RMQ_matrix(int v[], int n, int rmq[][N], int MAX_LEVEL){ /// Creates min() RMQ table "rmq" from Array "v"
/// Compute RMQ level 0
for(int i=0; i<n; ++i)
rmq[0][i] = v[i];
/// Compute RMQ levels 1 to MAX_LEVEL
for(int level = 1; level <= 17; ++level)
{
int sequence_length = 1 << level;
int last_sequence_index = n - sequence_length + 1;
for(int index = 0; index < last_sequence_index; ++index)
rmq[level][index] = min(rmq[level-1][index], rmq[level-1][index + sequence_length / 2]);
//for(int index = 0; index < last_sequence_index; ++index) cout<<rmq[level][index]<<" "; cout<<"\n";
}
}
int MSD(int x){ /// Base 2 MSD of number X
while(x & (x-1)) /// X isn't a power of 2 yet
x &= x-1; /// Remove X's LSD
return x;
}
int queryRMQ(int rmq[][N], int n, int a, int b){ /// Queries the RMQ table in interval [a, b]
int query_interval_length = b-a+1;
int sequence_length = MSD(query_interval_length); /// The maximal RMQ sequence length we can query
int level = log2(sequence_length);
int offset = query_interval_length - sequence_length;
return min(rmq[level][a], rmq[level][a + offset]); /// min <- [a, a + 2^level] U [a+offset, b]
}
int LMRM_values[2*N]; /// Left - Middle - Right - Middle
list<int> sons[N]; /// sons[x] = sons of node 'x'
int LMRM_length;
void LMRM_path(int crtNode){
LMRM_values[LMRM_length++] = crtNode;
for(list<int>::iterator it = sons[crtNode].begin(); it != sons[crtNode].end(); ++it){
LMRM_path(*it);
LMRM_values[LMRM_length++] = crtNode;
}
}
int main()
{
/// Local Variables
int rmqArray[NLOG][N]; /// rmqArray[level][index] = min(index, index+1, ..., index + 2^level);
int first_index[N]; /// first_index[i] = the index where number 'i' appears first in the array
int n,q;
/// Unit Testing :D
assert(MSD(16) == 16); /// 10000
assert(MSD(9) == 8); /// 01001
assert(MSD(7) == 4); /// 00111
/// Input
in>>n>>q;
for(int currNode=2; currNode<=n; ++currNode) /// n-1 fathers
{
int currFather;
in>>currFather;
sons[currFather].push_back(currNode);
}
//for(int i=1; i<=n; ++i) { cout<<i<<" => "; for(list<int>::iterator it = sons[i].begin(); it != sons[i].end(); ++it) cout<<*it<<" "; cout<<"\n"; }
/// Compute the LMRM path aray aka "Euler Path"
LMRM_length = 0;
LMRM_path(1);
for(int i=1; i<LMRM_length; ++i)
if(!first_index[LMRM_values[i]]) /// First index of element 'LMRM_values[i]' hasn't been set yet
first_index[LMRM_values[i]] = i;
//for(int i=0; i<LMRM_length; ++i) cout<<LMRM_values[i]<<" "; cout<<"\n";
/// Compute RMQ table
array_to_RMQ_matrix(LMRM_values, LMRM_length, rmqArray, NLOG);
/// Answer the queries
for(int i=0; i<q; ++i)
{
int leftBound, rightBound;
in>>leftBound>>rightBound;
int left_index = first_index[leftBound];
int right_index = first_index[rightBound];
if(left_index > right_index)
swap(left_index, right_index);
//cout<<left_index<<" "<<right_index<<" ";
out<<queryRMQ(rmqArray, n, left_index, right_index)<<"\n";
}
return 0;
}