Cod sursa(job #682509)

Utilizator claudiumihailClaudiu Mihail claudiumihail Data 19 februarie 2012 03:16:56
Problema Stramosi Scor 70
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.51 kb
#include <fstream>
#include <iostream>
#include <vector>
#include <queue>
#include <cstdlib>

#define MAXN 250001

using namespace std;

typedef unsigned int uint32;
typedef vector<vector<int> > Graph;
typedef vector<vector<int> > AncestorMatrix;

template<typename T, int defaultMaxCap=0>
class CQueue
{
public:
	CQueue(const size_t cap) :
		current(0),
		capacity(cap),
		size(0)
	{
		Q = (T*)malloc((cap+1)*sizeof(T));
	}
	
	CQueue() :
		current(0),
		capacity(defaultMaxCap),
		size(0)
	{
		Q = (T*)malloc((defaultMaxCap+1)*sizeof(T));
	}
	
	inline T front() const
	{
		return Q[current];
	}
	
	inline void push(const T& elem)
	{
		const size_t pos = (current+size) % capacity;
		size++;
		Q[pos] = elem;
	}
	
	inline void pop()
	{
		if (size != 0)
		{
			size--;
			current++;
			current %= capacity;
		}
	}
	
	inline bool empty() const
	{
		return (size == 0);
	}
	
	inline void clear()
	{
		current = 0;
		size = 0;
	}
	
	~CQueue()
	{
		free(Q);
	}

private:
	T* Q;
	size_t current;
	size_t capacity;
	size_t size;
};

int LookupTable[] =
{
    31, 30, 29, 28, 27, 26, 25, 24,
    23, 22, 21, 20, 19, 18, 17, 16,
    15, 14, 13, 12, 11, 10, 9, 8,
    7, 6, 5, 4, 3, 2, 1, 0
};

struct Identity
{
    Identity() :
        level(0),
        id(0)
    {}
    
    Identity(const unsigned char l, const int iid) :
        level(l),
        id(iid)
    {}

    unsigned char level;
    int id;
};

inline int GetMSB(const int mask)
{
    unsigned long res=0;

#ifdef _MSC_VER
    _BitScanReverse(&res, mask);
#else
    res = LookupTable[__builtin_clz(mask)];
#endif
    
    return res;
}

char matAncestorsSize[MAXN];
int matAncestors[MAXN][21];

int Query(int id, int degree)
{
    if (!degree)
        return id;

    while (degree && matAncestorsSize[id])
    {
        const int idMask = (1<<matAncestorsSize[id])-1;
        int msbIndex = GetMSB(degree & idMask);
        //cout << "MSB = " << msbIndex << endl;
        
        degree -= (1<<msbIndex);
        id = matAncestors[id][msbIndex];
        
        //cout << id << endl;
        //getchar();
    }
    
    if (degree)
    {
        return 0;
    }
    
    //cout << "Acestor is " << id << endl;
    
    return id;
}

int main()
{
    int n, m;
    Graph graph;
    //AncestorMatrix matAncestors;
    vector<int> vRoots;
    fstream fin("stramosi.in", fstream::in);
    fstream fout("stramosi.out", fstream::out);

    fin >> n >> m;
    //cout << n << " " << m << "\n";
    
    graph.resize(n+1);
    //matAncestors.resize(n+1);
    
    for (int i=1; i<=n; ++i)
    {
        int x;
        fin >> x;
        
        if (!x)
        {
            vRoots.push_back(i);
        }
        else
        {
            graph[x].push_back(i);
        }
    }
    
    /*for (uint32 i=0; i<vRoots.size(); ++i)
    {
        cout << vRoots[i] << " ";
    }
    cout << "\n";
    
    for (uint32 i=1; i<=n; ++i)
    {
        cout << i << "-> ";
        for (uint32 j=0; j<graph[i].size(); ++j)
        {
            cout << graph[i][j] << " ";
        }
        cout << "\n";
    }*/
    
    CQueue<Identity> Q(n);
    
    //queue<Identity> Q;
    for (uint32 i=0; i<vRoots.size(); ++i)
    {
        Q.push(Identity(0, vRoots[i]));
    }
    
    while (!Q.empty())
    {
        Identity current = Q.front();
        Q.pop();
        
        if (current.level > 0)
        {
            int level = 1;
            int parentID = matAncestors[current.id][0];
            
            while ((1<<(level)) <= current.level)
            {
                parentID = matAncestors[parentID][level-1];
                matAncestors[current.id][level] = parentID;
                matAncestorsSize[current.id]++;
                level++;
            }
        }
        
        for (uint32 i=0; i<graph[current.id].size(); ++i)
        {
            matAncestors[graph[current.id][i]][0] = current.id;
            matAncestorsSize[graph[current.id][i]] = 1;
            Q.push(Identity(current.level+1, graph[current.id][i]));
        }
    }
    
    /*cout << "Size = " << matAncestors[13].size() << endl;
    for (uint32 i=0; i<matAncestors[13].size(); ++i)
    {
        cout << matAncestors[13][i] << endl;
    }*/
    
    for (int i=0; i<m; ++i)
    {
        int p,q;
        
        fin >> q >> p;
        fout << Query(q, p) << "\n";
    }

    fin.close();
    fout.close();
    return 0;
}