Cod sursa(job #2095450)

Utilizator adireusadireus adireus Data 27 decembrie 2017 15:55:31
Problema Lowest Common Ancestor Scor 20
Compilator c Status done
Runda Arhiva educationala Marime 2.88 kb
#include <stdlib.h>
#include <stdio.h>

struct node {
	int data;
	struct node *next;
};

int segtree_get_size(int n)
{
        for (int i = 0; i <= 31; i++) {
                int x = 0x1 << i;
                if(x >= n)
                        return x;
        }

        return -1;
}

int list_add_front(struct node **head, int val)
{
	struct node *tmp;
	tmp = malloc(sizeof(struct node));
	tmp->data = val;
	tmp->next = *head;
	*head = tmp;
}

int dfs(struct node **tree, int root, int *eul, int *lev, int *idx, int level, int* i)
{
	eul[*i] = root;
	lev[*i] = level;
	idx[root] = *i;
	(*i)++;

	for(struct node *p = tree[root]; p != NULL; p = p->next) {
		dfs(tree, p->data, eul, lev, idx, level+1, i);
		eul[*i] = root;
		lev[*i] = level;
		(*i)++;
	}

	return 0;
}

void st_helper(int *segtree, int* array, int pos, int l, int r)
{
	int mid = (l + r) / 2;
	
	if (l == r) {
		segtree[pos] = l;
		return;
	}
	
	st_helper(segtree, array, 2 * pos, l, mid);
	st_helper(segtree, array,  2 * pos+1, mid+1, r);
	if (array[segtree[2 * pos]] < array[segtree[2 * pos + 1]])
		segtree[pos] = segtree[2 * pos];
	else 
		segtree[pos] = segtree[2 * pos + 1];

	return;
	
}

int get_min(int *segtree, int *array, int pos, int l, int r, int x, int y)
{
	int mid = (l + r) / 2;
	int m1, m2;

	if (x == l && y == r)
		return segtree[pos];
	// x y to the left
	if (x >= l && y <= mid) 
		return get_min(segtree, array, 2 * pos, l, mid, x, y);

	//x y to the right
	if(x >= mid+1 && y <= r)
		return get_min(segtree, array, 2 * pos + 1, mid+1, r, x, y);

	//x in left y in right

	m1 = get_min(segtree, array, 2 * pos, l, mid, x, mid);
	m2 = get_min(segtree, array, 2 * pos + 1, mid+1, r, mid+1, y);
	if(array[m1] < array[m2])
		return m1;
	else
		return m2;

	return -1;
}

void st_create(int **segtree, int* array, int n)
{
	int sn = segtree_get_size(n);
	*segtree = malloc((sn+1) * sizeof(int));

	for (int i = 0; i <= sn; i++)
		(*segtree)[i] = -1;

	st_helper(*segtree, array, 1, 0, n-1);
}

int main()
{
	FILE *infile, *outfile;
	int n, m, i;
	struct node **tree;
	int *euler, *level, *index;
	int *segtree;
	int count = 0;
	
	infile = fopen("lca.in", "r");
	outfile = fopen("lca.out", "w");
	
	fscanf(infile, "%d %d", &n, &m);

	tree = malloc((n+1) * sizeof(struct node*));
	for (i = 0; i <= n; i++)
		tree[i] = NULL;

	euler = malloc((2 * n - 1) * sizeof(int));	
	level = malloc((2 * n - 1) * sizeof(int));
	index = malloc((n+1) * sizeof(int));

	for (i = 1; i < n; i++) {
		int x;
		fscanf(infile, "%d", &x);
		list_add_front(&tree[x], i+1);
	}

	dfs(tree, 1, euler, level, index, 0, &count);
	st_create(&segtree, level, 2 * n -1);

	for (i = 0; i < m; i++) {
		int q1, q2;
		fscanf(infile, "%d %d", &q1, &q2);
		if (index[q1] > index[q2]) {
			int aux = q1; 
			q1 = q2;
			q2 = aux;
		}

		int x = get_min(segtree, level, 1, 0, 2 * n - 2, index[q1], index[q2]);
		fprintf(outfile, "%d\n", euler[x]);
	}
	fclose(infile);
	fclose(outfile);
	return 0;
}