Cod sursa(job #340609)

Utilizator savimSerban Andrei Stan savim Data 15 august 2009 17:11:32
Problema Arbore Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.04 kb
#include <stdio.h>
#include <math.h>
#include <vector>

using namespace std;

#define MAXX 1000020
#define MAX_N 100010
#define RAD 330
#define pb push_back

int n, m, k, rad, tip, p, q, s, st, dr;
int fol[MAX_N], poz[2][MAX_N], sir[MAX_N];

int start[RAD], stop[RAD];
int nr[MAXX], p2[32];
int A[MAX_N], plus[RAD], gas[RAD][35000];

vector <int> v[MAX_N];

void df(int nod) {
    fol[nod] = 1;
	sir[++k] = nod;
	poz[0][nod] = k;

	int len = v[nod].size();
	for (int i = 0; i < len; i++)
		if (!fol[v[nod][i]])
			df(v[nod][i]);

	fol[nod] = 0;			
	poz[1][nod] = k;
}
        
void cit() {
	freopen("arbore.in", "r", stdin);
	freopen("arbore.out", "w", stdout);

	scanf("%d %d", &n, &m);
	for (int i = 1; i < n; i++) {
    	scanf("%d %d", &p, &q);
		v[p].pb(q);
		v[q].pb(p);
	}

	df(1);
}

inline int loc(int x) {
	if (x % rad) return x / rad + 1;
	else return x / rad;
}

void init() {
	rad = (int) sqrt(n);
	if (rad * rad < n)
        rad++;

	for (int i = 1; i <= rad; i++) {
		start[i] = rad * (i - 1) + 1;
		stop[i] = rad * i;
		gas[i][0] = 1;
	}
    if (stop[rad] > n) stop[rad] = n;
    if (stop[rad - 1] > n) stop[rad - 1] = n;
    
	for (int i = 0; i <= 31; i++)
		p2[i] = 1 << i;
}

void update(int val, int poz, int ok) {
	int x = val / 30;
	int y = val % 30;

	if (ok) {
	   if (!(gas[poz][x] & p2[y]))
			gas[poz][x] += p2[y];
	}
	else gas[poz][x] -= p2[y];
}

void work1() {
	scanf("%d %d", &p, &s);

	//fac update intre poz[0][p] si poz[1][p]
	st = loc(poz[0][p]);
	dr = loc(poz[1][p]);

	if (st != dr) {
		for (int i = start[st]; i <= stop[st]; i++)
			nr[A[i]] = 0;
		for (int i = start[st]; i <= stop[st]; i++)
			nr[A[i]]++;

		for (int i = poz[0][p]; i <= stop[st]; i++) {
			update(A[i] + s, st, 1);

			nr[A[i] + s]++;
			if (nr[A[i]] == 1)
				update(A[i], st, 0);
			nr[A[i]]--;

			A[i] += s;
		}

		for (int i = st + 1; i <= dr - 1; i++)
			plus[i] += s;

		for (int i = start[dr]; i <= stop[dr]; i++)
	        nr[A[i]] = 0;
    	for (int i = start[dr]; i <= stop[dr]; i++)
	        nr[A[i]]++;
		for (int i = start[dr]; i <= poz[1][p]; i++) {
		    update(A[i] + s, dr, 1);

			nr[A[i] + s]++;
        	if (nr[A[i]] == 1)
    	        update(A[i], dr, 0);
	        nr[A[i]]--;
		
			A[i] += s;
		}
	}
	else {
  	    for (int i = start[st]; i <= stop[st]; i++)
            nr[A[i]] = 0;
        for (int i = start[st]; i <= stop[st]; i++)
            nr[A[i]]++;
    	for (int i = poz[0][p]; i <= poz[1][p]; i++) {
        	update(A[i] + s, st, 1);

			nr[A[i] + s]++;
			if (nr[A[i]] == 1) 
				update(A[i], st, 0);
			nr[A[i]]--;

			A[i] += s;
		}
	}
}

inline int find(int poz, int val) {
	int p = val / 30;
	int q = val % 30;

	if (gas[poz][p] & p2[q]) return 1;
	return 0;
}

void work2() {
	scanf("%d", &s);

	for (int i = 1; i <= rad; i++)
		if (find(i, s - plus[i]))
        	for (int j = start[i]; j <= stop[i]; j++)
				if (A[j] + plus[i] == s) {
					printf("%d\n", sir[j]);
					return;
				}
	printf("-1\n");
}

void solve() {
	init();

	while (m--)	{
		scanf("%d", &tip);
		if (tip == 1) 
			work1();
		else 
			work2();
	} 
}

int main() {

	cit();
	solve();

	return 0;
}