Cod sursa(job #21758)

Utilizator m_dersidanDersidan Mihai m_dersidan Data 24 februarie 2007 11:37:57
Problema Atac Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.28 kb
# include <stdio.h>

# define  _fin  "atac.in"
# define  _fout "atac.out"

# define  maxi  0x7FFFFFFF
# define  maxn  32767
# define  logn  16


typedef struct nod
{
	int val;
	nod *next;
}	*pnod;


int n, m, p;
pnod v[maxn];

const int max_elen = 4*maxn+4;

// pentru LCA
int e[max_elen],			// parcurgere euler
	a[max_elen], 			// adancime(nivel)
	pos[maxn+1],			// pozitia din parc euler
    minval[logn+1][max_elen],
	minpos[logn+1][max_elen],
	elen;

int dmin[logn+1][maxn+1],
	stram[logn+1][maxn+1],
	niv[maxn+1],
	logtab[max_elen+1];


inline int min(int x, int y) { return x<y?x:y; }


void readf()
{
	int i, u, vv;
	pnod c;
	scanf("%d%d%d", &n, &m, &p);

	for (i = 2; i <= n; i++)
	{
		scanf("%d %d", &u, &vv);
		
		stram[ 0 ][ i ] = u, dmin [ 0 ][ i ] = vv;
		
		c = new nod;
		c->val = i, c->next = v[u], v[u] = c;
	}
}

void euler(int x, int nivel, int tat)
{
	e[++elen] = x;
	niv[x] = nivel;
	a[elen] = nivel;
	
	for (pnod q=v[x]; q; q=q->next)
		if (q->val != tat)
		{
			euler(q->val, nivel+1, x);
			e[++elen] = x, a[elen] = nivel;
	    }
}

void precompute()
{
	int i, k, lg, _logn;

	euler(1, 1, 0);

	logtab[0] = -1;
	
	for (i=1; i<=elen; i++)
		logtab[i] = logtab[i>>1]+1;

	// pozitia fiecarui nod in parcurgerea euleriana
	for (i=1; i<=elen; i++)
		if (!pos[ e[i] ]) pos[ e[i] ] = i;

	lg = logtab[elen];

	// adancimea nodului i
	for (i = 1; i<=elen; i++)
		minval[0][i] = a[i],
		minpos[0][i] = i;

	for (k=1; k<=lg; k++)
		for (i=1; i<=elen - (1<<k) + 1; i++)
			if (minval[k-1][i] < minval[k-1][i + (1 << (k-1))])	// adancimea minima dintre i si i+1, i si i+2, i si i+4 ...
			{
				minval[k][i] = minval[k-1][i];
				minpos[k][i] = minpos[k-1][i];
			}
			else
			{
				minval[k][i] = minval[k-1][i + (1 << (k-1))];
				minpos[k][i] = minpos[k-1][i + (1 << (k-1))];
			}

	// distante
	_logn = logtab[n];

	for (k = 1; k <= _logn; k++)
		for (i = 1; i <= n; i++)
			stram[k][i] = stram[k-1][ stram[k-1][i] ];

	for (k = 1; k <= _logn; k++)
		for (i = 1; i <= n; i++)
			dmin[k][i] = min( dmin[k-1][i], dmin[k-1][ stram[k-1][i] ]);
}

int query(int x, int y)
{
	int aux, lca, l, r, k, q, p;

	// O(1) pentru lca
	if (x == y) return 0;
	l = pos[x], r = pos[y];
	if (l > r) l ^= r ^= l ^= r;

	k = logtab[r-l+1];

	if ( minval[k][l] <= minval[k][r-(1<<k)+1] )
		lca = e[ minpos[k][l] ];
	else
		lca = e[ minpos[k][r-(1<<k)+1] ];

	// O(log(N))
	aux = maxi;

	if (p = niv[x] - niv[lca])
	{
		q = x;
		for (r=0; p; p>>=1, r++)
			if (p & 1)
			{
				if (aux > dmin[r][q])
					aux = dmin[r][q];
				
				q = stram[r][q]; 
			}
	}

	if (p = niv[y] - niv[lca])
	{
		q = y;
		
		for (r = 0; p; p >>= 1, r++)
			if (p & 1)
			{
				if (aux > dmin[r][q])
					aux = dmin[r][q];
				
				q = stram[r][q];
			}
	}

	return aux;
}

int main()
{
	int i, x, y, a, b, c, d, z;

	freopen(_fin, "r", stdin);
	freopen(_fout, "w", stdout);

	readf();
	precompute();

	scanf("%d %d %d %d %d %d", &x, &y, &a, &b, &c, &d);

	for (i = 1; i <= m-p; i++)
	{
		z = query(x, y);
		x = (x*a + y*b) % n + 1;
		y = (y*c + z*d) % n + 1;
	}

	for (; i <= m; i++)
	{
		printf("%d\n", z = query(x, y));
		x = (x*a + y*b) % n + 1;
		y = (y*c + z*d) % n + 1;
	}

	return 0;
}