Pagini recente » Cod sursa (job #1875842) | Cod sursa (job #1611138) | Cod sursa (job #1075499) | Cod sursa (job #2253365) | Cod sursa (job #1146967)
//O(nlogn+m) reducere la rmq apoi sparse table (ideea de pe tocoder)
#include <fstream>
#include <vector>
class RMQ{
private:
std::vector< std::vector<unsigned> > ST;
std::vector< unsigned > l;
public:
RMQ(std::vector<unsigned> lin){
l=lin;
unsigned n=l.size(), temp=n, logn=0;
while(temp>>=1) ++logn;
ST.resize(logn+1,std::vector<unsigned>(n));
for(unsigned i=0;i<n;++i) ST[0][i]=i;
for(unsigned j=1;j<=logn;++j)
for(unsigned i=0;i+(1<<j)-1<n;++i)
if(l[ST[j-1][i]]<l[ST[j-1][i+(1<<(j-1))]]) ST[j][i]=ST[j-1][i];
else ST[j][i]=ST[j-1][i+(1<<(j-1))];
}
unsigned get(unsigned a, unsigned b){
unsigned sz=b-a+1, k=0;
while(sz>>=1) ++k;
if(l[ST[k][a]]<l[ST[k][b-(1<<k)+1]]) return ST[k][a];
else return ST[k][b-(1<<k)+1];
}
};
inline void euler_dfs(std::vector<unsigned> &euler, std::vector<unsigned> &l,
std::vector<unsigned> &first, unsigned n, std::istream &fin){
std::vector< std::vector<unsigned> > Adj(n+1);
std::vector<unsigned> aind(n+1,0);
unsigned nreuler=n;
for(unsigned i=2;i<=n;++i){ unsigned x; fin>>x; Adj[x].push_back(i); ++nreuler; }
euler.resize(nreuler); l.resize(nreuler); first.resize(n+1,0);
std::vector<unsigned> niv(n+1);
unsigned ei=0;
std::vector<unsigned> st(n);
st[0]=1; l[0]=0; niv[1]=0;
int si=0;
while(si>-1){
euler[ei]=st[si];
if(first[st[si]]==0) first[st[si]]=ei;
l[ei]=niv[st[si]];
ei++;
if(aind[st[si]]<Adj[st[si]].size()){
unsigned nghb=Adj[st[si]][aind[st[si]]++];
niv[nghb]=niv[st[si]]+1;
st[++si]=nghb;
}
else --si;
}
first[1]=0;
}
int main(){
std::ifstream fin("lca.in");
std::ofstream fout("lca.out");
unsigned n,m; fin>>n>>m;
std::vector<unsigned> euler;
std::vector<unsigned> l;
std::vector<unsigned> first;
euler_dfs(euler,l,first,n,fin);
RMQ rmql(l);
for(unsigned i=0;i<m;++i){
unsigned a,b; fin>>a>>b;
if(first[a]>first[b]){ unsigned temp=a; a=b; b=temp; }
fout<<euler[rmql.get(first[a],first[b])]<<'\n';
}
}