Submission #1044856

#TimeUsernameProblemLanguageResultExecution timeMemory
1044856vjudge1Bridges (APIO19_bridges)C++17
27 / 100
156 ms8804 KiB
#include <bits/stdc++.h>

using i64 = long long;

#ifdef DEBUG
	#include "debug.h"
#else 
	#define debug(...) void(23)
#endif

constexpr int INF = int(1E9);
constexpr int maxN = int(5E4) + 5;

std::vector<int> adj[maxN];

struct DSU {
	std::vector<int> par, siz;
	DSU() : DSU(0) {}
	DSU(int n) { init(n); }
	void init(int n) {
		par.assign(n, 0);
		siz.assign(n, 1);
		std::iota(par.begin(), par.end(), 0);
	}
	int get(int x) {
		while(x != par[x]) {
			x = par[x] = par[par[x]];
		}
		return x;
	}
	bool unite(int a, int b) {
		a = get(a), b = get(b);
		if(a == b) {
			return false;
		} else if(siz[a] > siz[b]) {
			std::swap(a, b);
		}
		par[a] = b;
		siz[b] += siz[a];
		return true;
	}
	int size(int x) {
		return siz[get(x)];
	}
};

#define def int mid = (l + r) >> 1, rv = v + ((mid - l + 1) << 1)
struct segtree {
	struct node {
		int val;
		node() : val(INF) {}
		node(int x) : val(x) {}
	};
	node unite(node lhs, node rhs) {
		return {std::min(lhs.val, rhs.val)};
	}
	int n;
	std::vector<node> tree;
	segtree(int _n) : n(_n), tree(n << 1) {}
	void modify(int v, int l, int r, int p, int x) {
		if(l == r) {
			tree[v] = {x};
			return;
		}
		def;
		if(p <= mid) {
			modify(v + 1, l, mid, p, x);
		} else {
			modify(rv, mid + 1, r, p, x);
		}
		tree[v] = unite(tree[v + 1], tree[rv]);
	}
	void modify(int p, int x) {
		assert(0 <= p && p < n);
		modify(0, 0, n - 1, p, x);
	}

	int query(int v, int l, int r, int ql, int qr) {
		if(ql <= l && r <= qr) {
			return tree[v].val;
		}
		def;
		if(qr <= mid) {
			return query(v + 1, l, mid, ql, qr);
		} else if(mid + 1 <= ql) {
			return query(rv, mid + 1, r, ql, qr);
		}
		return std::min(query(v + 1, l, mid, ql, qr), 
						query(rv, mid + 1, r, ql, qr));
	}
	int query(int l, int r) {
		if(l > r) {
			return INF;
		}
		return query(0, 0, n - 1, l, r);
	}
};

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

	int N, M, Q;
	std::cin >> N >> M;
	std::vector<int> A(M), B(M), C(M), t(N);
	for(int i = 0; i < M; ++i) {
		std::cin >> A[i] >> B[i] >> C[i];
		--A[i], --B[i];
		t[A[i]] += 1;
		t[B[i]] += 1;
		adj[A[i]].emplace_back(i);
		adj[B[i]].emplace_back(i);
	}

	std::cin >> Q;
	bool good = true;
	int cnt = 0;
	for(int i = 0; i < N; ++i) {
		good &= t[i] <= 2;
		cnt += t[i] == 1;
	}

	good &= cnt == 2;

	bool flag = true;
	#ifdef LOCAL
		flag = false;
	#endif
	if(N <= 1000 && M <= 1000 && Q <= 10000 && flag) {
		std::vector<int> ord(M);
		std::iota(ord.begin(), ord.end(), 0);
		DSU dsu;
		for(int i = 0; i < Q; ++i) {
			debug(i);
			int T;
			std::cin >> T;
			if(T == 1) {
				int j, R;
				std::cin >> j >> R;
				--j;
				C[j] = R;
			} else {
				int S, W;
				std::cin >> S >> W;
				--S;
				dsu.init(N);
				std::sort(ord.begin(), ord.end(), [&](int lhs, int rhs) {
					return C[lhs] < C[rhs];
				});
				debug("wtf");
				for(int j : ord) {
					if(C[j] >= W) {
						dsu.unite(A[j], B[j]);
					}
				}
				debug("wtf");
				std::cout << dsu.size(S) << '\n';
			}
		}
		return 0;
	} else if(good) {
		int root = 0;
		while(adj[root].size() == 2) {
			root += 1;
		}

		debug(root);

		int cur = root, par = root, timer = 0, timernode = 0;
		std::vector<int> gone, taken(N), timen(N);
		do {
			timen[cur] = timernode++;
			for(int i : adj[cur]) {
				int u = A[i] ^ B[i] ^ cur;
				if(u != par) {
					taken[i] = timer++;
					gone.emplace_back(i);
					par = cur;
					cur = u;
					break;
				}
			}
			debug(cur, par);
		} while(adj[cur].size() == 2);
		timen[cur] = timernode++;

		debug(gone, taken, timen);

		segtree seg(N - 1);
		for(int i = 0; i < N - 1; ++i) {
			seg.modify(taken[i], C[i]);
		}
		for(int _ = 0; _ < Q; ++_) {
			int T;
			std::cin >> T;
			if(T == 1) {
				int i, r;
				std::cin >> i >> r;
				--i;
				seg.modify(taken[i], r);
			} else {
				int S, W;
				std::cin >> S >> W;
				--S;
				int L, R;
				{
					int lo = 0, hi = timen[S];
					while(lo < hi) {
						int mid = (lo + hi) >> 1;
						if(W <= seg.query(lo, hi - 1)) {
							hi = mid;
						} else {
							lo = mid + 1;
						}
					}
					L = lo;
				}
				{
					int lo = timen[S], hi = N - 1;
					while(lo < hi) {
						int mid = (lo + hi + 1) >> 1;
						if(W <= seg.query(lo, hi - 1)) {
							lo = mid;
						} else {
							hi = mid -1;
						}
					}
					R = lo;
				}
				debug(L, R);
				std::cout << R - L + 1 << '\n';
			}
		}

		return 0;
	}

	std::vector<int> ord(M);
	std::iota(ord.begin(), ord.end(), 0);
	std::sort(ord.begin(), ord.end(), [&](int lhs, int rhs) {
		return C[lhs] > C[rhs];
	});

	std::vector<int> ans(Q);
	std::vector<std::pair<int, int>> qq(Q);
	for(int i = 0; i < Q; ++i) {
		int T, S, W;
		std::cin >> T >> S >> W;
		--S;
		assert(T == 2);
		qq[i] = {W, S};
	}

	std::vector<int> qrd(Q);
	std::iota(qrd.begin(), qrd.end(), 0);
	std::sort(qrd.begin(), qrd.end(), [&](int lhs, int rhs) {
		return qq[lhs] > qq[rhs];
	});

	DSU dsu(N);
	int ptr = 0;
	for(int i : qrd) {
		while(ptr < M && C[ord[ptr]] >= qq[i].first) {
			dsu.unite(A[ord[ptr]], B[ord[ptr]]);
			ptr += 1;
		}
		ans[i] = dsu.size(qq[i].second);
	}

	for(int i = 0; i < Q; ++i) {
		std::cout << ans[i] << '\n';
	}

	return 0;
}
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...