Submission #120465

#TimeUsernameProblemLanguageResultExecution timeMemory
120465perchemSynchronization (JOI13_synchronization)C++14
100 / 100
234 ms9848 KiB
#include <iostream>
#include <cstdint>
#include <random>
#include <utility>
#include <cassert>

class Node {
private:
	static std::mt19937 rnd;

	Node *l, *r, *par;
	Node *pp;
	uint32_t p;
	bool lazy;
	uint32_t size;


	void push_lazy() {
		if (lazy) {
			if (l) {
				l->reverse();
			}
			if (r) {
				r->reverse();
			}
			lazy = false;
		}
	}
	void push_lazy_root() {
		if (par) {
			par->push_lazy_root();
		}
		push_lazy();
	}

	void recalc() {
		par = nullptr;
		size = 1;

		if (l) {
			size += l->size;
			l->par = this;
			if (l->pp) {
				pp = l->pp;
				l->pp = nullptr;
			}
		}
		if (r) {
			size += r->size;
			r->par = this;
			if (r->pp) {
				pp = r->pp;
				r->pp = nullptr;
			}
		}
	}

public:
	uint32_t inf; //0 for non root, actual value for root
	
	void reverse() {
		lazy = !lazy;
		std::swap(l, r);
	}

	Node(): l(nullptr), r(nullptr), par(nullptr), pp(nullptr), p(rnd()),
		lazy(false), size(1), inf(1) {}
	
	static Node* merge(Node *a, Node *b) {
		if (a == nullptr) {
			return b;
		} else if (b == nullptr) {
			return a;
		} else if (a->p > b->p) {
			a->push_lazy();
			a->r = merge(a->r, b);
			a->recalc();
			return a;
		} else {
			b->push_lazy();
			b->l = merge(a, b->l);
			b->recalc();
			return b;
		}
	}
	static std::pair<Node*, Node*> split(Node *a, uint32_t sz) {
		if (a == nullptr) {
			return {nullptr, nullptr};
		}
		a->push_lazy();
		uint32_t lSz = a->l ? a->l->size : 0;
		if (lSz >= sz) {
			auto s = split(a->l, sz);
			a->l = s.second;
			a->recalc();
			return {s.first, a};
		} else {
			auto s = split(a->r, sz - lSz - 1);
			a->r = s.first;
			a->recalc();
			return {a, s.second};
		}
	}
	Node *treap_root() {
		assert(par != this);
		return par ? par->treap_root() : this;
	}
	uint32_t ind() {
		push_lazy_root();
		uint32_t ans = l ? l->size : 0;

		Node *v = this;
		while (v->par) {
			if (v->par->r == v) {
				ans += v->par->l ? v->par->l->size : 0;
				ans++;
			}
			v = v->par;
		}
		return ans;
	}
	Node *left_most() {
		push_lazy();
		return l ? l->left_most() : this;
	}

	void split_at_node() {
		uint32_t i = ind();
		Node *root = treap_root();
		Node *rootPp = root->pp;
		root->pp = nullptr;

		//std::cerr << "i: " << i << "\n";

		auto s = split(root, i + 1);
		s.first->pp = rootPp;
		if (s.second) {
			s.second->pp = this;
		}
	}

	void access() {
		split_at_node();
		//std::cerr << "split_at_node();\n";
		Node *v = treap_root();
		while (v->pp) {
			Node *u = v->pp;
			u->split_at_node();
			v->pp = nullptr;
			//assert(u->treap_root() != v);
			v = merge(u->treap_root(), v);
		}
	}

	void reroot() {
		access();
		Node *treapRoot = treap_root();

		Node *treeRoot = treapRoot->left_most();
		uint32_t inf = treapRoot->left_most()->inf;
		treeRoot->inf = 0;
		
		treapRoot->reverse();
		treapRoot->left_most()->inf = inf;
	}

	static void link(Node *a, Node *b, uint32_t prevInf = 0) {
		a->access();
		Node *rootA = a->treap_root()->left_most();
		b->reroot();

		rootA->inf += b->inf - prevInf;
		b->inf = 0;

		b->treap_root()->pp = a;
	}
	uint32_t depth() {
		access();
		return treap_root()->size;
	}
	static uint32_t cut(Node *a, Node *b) {
		if (a->depth() < b->depth()) {
			std::swap(a, b);
		}
		a->inf = b->treap_root()->left_most()->inf;
		b->access();
		a->treap_root()->pp = nullptr;
		return a->inf;
	}
	void print_treap() {
	}

	uint32_t id();
};

std::mt19937 Node::rnd(27071999);

const uint32_t MAX_N = 1e5 + 10;
const uint32_t MAX_M = 2e5 + 10;

struct Edge {
	uint32_t a, b;
	uint32_t lastI;
	bool on;

	Edge(): lastI(0), on(false) {}
};

std::vector<Node> nodes;
std::vector<Edge> edges;
uint32_t m, q;

uint32_t Node::id() {
	return this - &nodes[0] + 1;
}

void print_info() {
	for (Node &n : nodes) {
		n.access();
		std::cerr << "(" << n.id() << ": " << n.treap_root()->left_most()->id();
		std::cerr << " " << n.treap_root()->left_most()->inf << ") ";
	}
	std::cerr << "\n";
}

void print_treaps() {
	for (uint32_t i = 0;i < nodes.size();i++) {
		std::cerr << i << ": " << nodes[i].treap_root() - &nodes[0] << "; ";
		std::cerr << "accessing it\n";
		nodes[i].access();
	}
	std::cerr << "\n";
}
void input() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);

	uint32_t n;
	std::cin >> n >> m >> q;
	nodes.resize(n);

	edges.resize(n - 1);
	for (Edge &e : edges) {
		std::cin >> e.a >> e.b;
		e.a--;
		e.b--;
	}
}

void do_updates() {
	//print_treaps();
	for (uint32_t i = 0;i < m;i++) {
		uint32_t j;
		std::cin >> j;
		Edge &e = edges[j - 1];
		if (e.on) {
			e.lastI = Node::cut(&nodes[e.a], &nodes[e.b]);
		} else {
			Node::link(&nodes[e.a], &nodes[e.b], e.lastI);
		}
		e.on = !e.on;
		//print_info();

		//print_treaps();
	}
}

void ans_queries() {
	for (uint32_t i = 0;i < q;i++) {
		uint32_t a;
		std::cin >> a;
		nodes[a - 1].access();
		std::cout << nodes[a - 1].treap_root()->left_most()->inf << "\n";
	}
}

int main() {
	input();
	do_updates();
	ans_queries();
}

#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...