Submission #120253

#TimeUsernameProblemLanguageResultExecution timeMemory
120253JustInCaseSynchronization (JOI13_synchronization)C++17
100 / 100
275 ms12272 KiB
#include <bits/stdc++.h>

const int32_t MAX_N = 1e5;
std::mt19937 mt(69);

struct Edge {
	bool toggled;
	int32_t x, y, w;

	Edge() {}
	Edge(int32_t _x, int32_t _y) : x(_x), y(_y), w(0), toggled(false) {}
};

struct Node {
	bool rev;
	int32_t sz, prior, sum, id;
	Node *l, *r, *par, *pp;

	Node() {}
	Node(int32_t _id) : id(_id) {
		sz = 1;
		prior = mt();
		sum = 1;

		rev = false;

		l = nullptr;
		r = nullptr;
		par = nullptr;
		pp = nullptr;
	}

	static int32_t get_size(Node *x) {
		return (x ? x->sz : 0);
	}

	static void push_lazy(Node *x) {
		if(!x) {
			return;
		}

		if(x->rev) {
			std::swap(x->l, x->r);

			if(x->l) {
				x->l->rev ^= 1;
			}
			if(x->r) {
				x->r->rev ^= 1;
			}

			x->rev = false;
		}
	}

	static void pull_info(Node *x) {
		if(!x) {
			return;
		}

		x->sz = get_size(x->l) + get_size(x->r) + 1;
		
		x->par = nullptr;
		if(x->l) {
			x->l->par = x;
		}
		if(x->r) {
			x->r->par = x;
		}

		if(x->l && x->l->pp) {
			x->pp = x->l->pp;
			x->l->pp = nullptr;
		}
		if(x->r && x->r->pp) {
			x->pp = x->r->pp;
			x->r->pp = nullptr;
		}
	}

	static Node* merge(Node *x, Node *y) {
		push_lazy(x);
		push_lazy(y);

		if(!x) {
			return y;
		}
		if(!y) {
			return x;
		}

		if(x->prior > y->prior) {
			x->r = merge(x->r, y);
			pull_info(x);
			return x;
		}
		else {
			y->l = merge(x, y->l);
			pull_info(y);
			return y;
		}
	}

	static std::pair< Node*, Node* > split(Node *x, int32_t key, int32_t add = 0) {
		push_lazy(x);

		if(!x) {
			return { nullptr, nullptr };
		}

		int32_t currKey = add + get_size(x->l);
		if(currKey <= key) {
			auto aux = split(x->r, key, currKey + 1);
			x->r = aux.first;
			
			pull_info(x);
			
			return { x, aux.second };
		}
		else {
			auto aux = split(x->l, key, add);
			x->l = aux.second;
			
			pull_info(x);

			return { aux.first, x };
		}
	}

	static Node* split_after(Node *x) {
		int32_t pos = get_pos(x);
		Node *u = get_root(x);
		
		Node *pp = u->pp;
		u->pp = nullptr;

		auto aux = split(u, pos);
		
		if(aux.second) {
			aux.second->pp = x;
		}
		u = aux.first;
		u->pp = pp;

		return u;
	}

	static int32_t get_pos(Node *x) {
		int32_t pos = get_size(x->l);
		while(x->par) {
			if(x->rev) {
				pos = get_size(x) - pos - 1;
			}
			if(x->par->r == x) {
				pos += get_size(x->par->l) + 1;	
			}
			
			x = x->par;
		}

		if(x->rev) {
			pos = get_size(x) - pos - 1;
		}

		return pos;
	}

	static Node* get_root(Node *x) {
		while(x->par) {
			x = x->par;
		}

		return x;
	}
};

Node *nodes[MAX_N + 5];
Edge edges[MAX_N + 5];

Node* access(Node *x) {
	Node *u = Node::split_after(x);
	while(u->pp) {
		Node *v = u->pp;
		v = Node::split_after(v);
		u->pp = nullptr;
		u = Node::merge(v, u);
	}
	return u;
}

Node* get_tree_root(Node *x) {
	x = access(x);
	while(x->l) {
		x = x->l;
	}

	return x;
}

void change_root(Node *x) {
	int32_t treeSum = get_tree_root(x)->sum;

	Node *v = access(x);
	v->rev ^= 1;

	Node *u = get_tree_root(x);
	u->sum = treeSum;
}

void link(Node *x, Node *y) {
	change_root(x);
	x->pp = y;
}

void cut(Node *x, Node *y) {
	change_root(x);
	y = access(y);

	Node::split(y, 0);
}

void toggle_edge(int32_t x) {
	if(edges[x].toggled) {
		int32_t sum = get_tree_root(nodes[edges[x].x])->sum;
		cut(nodes[edges[x].x], nodes[edges[x].y]);
		
		edges[x].w = sum;
		Node *v = get_tree_root(nodes[edges[x].x]);
		Node *u = get_tree_root(nodes[edges[x].y]);

		v->sum = sum;
		u->sum = sum;
	}
	else {
		int32_t sumX = get_tree_root(nodes[edges[x].x])->sum;
		int32_t sumY = get_tree_root(nodes[edges[x].y])->sum;

		link(nodes[edges[x].x], nodes[edges[x].y]);

		Node *u = get_tree_root(nodes[edges[x].x]);
		u->sum = sumX + sumY - edges[x].w;
	}

	edges[x].toggled ^= 1;
}

int32_t answer_query(Node *x) {
	return get_tree_root(x)->sum;
}

int main() {
	std::ios_base::sync_with_stdio(false);
	std::cin.tie(nullptr);

	int32_t n, m, q;
	std::cin >> n >> m >> q;
	
	for(int32_t i = 1; i <= n; i++) {
		nodes[i] = new Node(i);
	}

	for(int32_t i = 1; i <= n - 1; i++) {
		int32_t x, y;
		std::cin >> x >> y;

		edges[i] = Edge(x, y);
	}

	for(int32_t i = 0; i < m; i++) {
		int32_t x;
		std::cin >> x;
		
		toggle_edge(x);
	}

	for(int32_t i = 0; i < q; i++) {
		int32_t x;
		std::cin >> x;

		std::cout << answer_query(nodes[x]) << '\n';
	}
}

Compilation message (stderr)

synchronization.cpp: In constructor 'Edge::Edge(int32_t, int32_t)':
synchronization.cpp:8:16: warning: 'Edge::w' will be initialized after [-Wreorder]
  int32_t x, y, w;
                ^
synchronization.cpp:7:7: warning:   'bool Edge::toggled' [-Wreorder]
  bool toggled;
       ^~~~~~~
synchronization.cpp:11:2: warning:   when initialized here [-Wreorder]
  Edge(int32_t _x, int32_t _y) : x(_x), y(_y), w(0), toggled(false) {}
  ^~~~
#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...