Cod sursa(job #1742836)

Utilizator bciobanuBogdan Ciobanu bciobanu Data 17 august 2016 10:38:40
Problema Arbore Scor 100
Compilator cpp Status done
Runda Lista lui wefgef Marime 3.31 kb
#include <cstdio>
#include <cstring>
#include <bitset>
#include <ctime>
#include <random>

#define MaxN 100050
#define MaxS 1000050
#define BUCKET 500
#define MaxBuckets 410
#define NIL -1

#define RANDOM_PASS 100

using namespace std;

struct Edge {
	int v;
	int next;
};

Edge l[2 * (MaxN - 1)];
int adj[MaxN];
int sum[2 * MaxN + BUCKET];

bitset <MaxS + 2> H[MaxBuckets];
int lazy[MaxBuckets];
int euler[2 * MaxN];
pair <int, int> node2Euler[MaxN];
int ptr;

int numBuckets;

static inline void addEdge(const int &u, const int &v, const int &pos) {
	l[pos].v =v;
	l[pos].next = adj[u];
	adj[u] = pos;
}

void DFS(int u, int parent) {
	euler[ptr] = u;
	node2Euler[u].first = ptr++;
	for (int i = adj[u]; i != NIL; i = l[i].next) {
		if (l[i].v != parent) {
			DFS(l[i].v, u);
		}
	}
	euler[ptr] = u;
	node2Euler[u].second = ptr++;
}

static inline int getRandom(void) {
	static mt19937 gen(time(0));
	int x = gen();
	return x < 0 ? -x : x;
}

static inline int randomCheck(const int &need) {
	for (int i = 0; i < RANDOM_PASS; i++) {
		int bucket = getRandom() % (numBuckets + 1);
		
		if (need - lazy[bucket] >= 0 && H[bucket][need - lazy[bucket]]) {
			return bucket;
		}
	}
	return -1;
}

int main() {
	freopen("arbore.in", "r", stdin);
	freopen("arbore.out", "w", stdout);
	int N, Q;
	int u, v;
	int opType, add;
	
	scanf("%d%d", &N, &Q);
	memset(adj, NIL, 4 * N);
	for (int i = 1; i < N; i++) {
		scanf("%d%d", &u, &v);
		addEdge(u - 1, v - 1, 2 * i - 2);
		addEdge(v - 1, u - 1, 2 * i - 1);
	}
	
	DFS(0, -1);
	numBuckets = -1;
	for (int i = 0; i < ptr; i++) {
		numBuckets += (i == i / BUCKET * BUCKET);
		H[numBuckets][0] = 1;
	}
	
	while (ptr != ptr / BUCKET * BUCKET) {
		sum[ptr++] = MaxS + 1;
	}
	
	while (Q--) {
		scanf("%d", &opType);
		if (opType == 1) {
			scanf("%d%d", &u, &add); u--;
			
			int bucket = node2Euler[u].first / BUCKET;
			int startBucket = bucket * BUCKET;
			int endBucket = startBucket + BUCKET;
			
			for (int i = startBucket; i < endBucket; i++) {
				H[bucket][sum[i]] = 0;
			}
			for (int i = node2Euler[u].first; (i < endBucket) && (i <= node2Euler[u].second); i++) {
				sum[i] += add;
			}
			for (int i = startBucket; i < endBucket; i++) {
				H[bucket][sum[i]] = 1;
			}
			
			if (node2Euler[u].second / BUCKET != bucket) {
				int fnBucket = node2Euler[u].second / BUCKET;
				for (int i = bucket + 1; i < fnBucket; i++) {
					lazy[i] += add;
				}
				startBucket = fnBucket * BUCKET;
				endBucket = startBucket + BUCKET;
				for (int i = startBucket; i < endBucket; i++) {
					H[fnBucket][sum[i]] = 0;
				}
				for (int i = startBucket; i <= node2Euler[u].second; i++) {
					sum[i] += add;
				}
				for (int i = startBucket; i < endBucket; i++) {
					H[fnBucket][sum[i]] = 1;
				}
			}
		} else {
			scanf("%d", &add);
			
			int bucket = randomCheck(add);
			
			if (bucket == -1) {
				do {
					bucket++;
				} while (bucket <= numBuckets && (add - lazy[bucket] < 0 || !H[bucket][add - lazy[bucket]]));
			}
			
			if (bucket <= numBuckets) {
				add -= lazy[bucket];
				bucket *= BUCKET;
				while (sum[bucket] != add) {
					bucket++;
				}
				printf("%d\n", 1 + euler[bucket]);
			} else {
				puts("-1");
			}
		}
	}
	fclose(stdin);
	fclose(stdout);
	return 0;
}