제출 #222886

#제출 시각아이디문제언어결과실행 시간메모리
222886atoizBridges (APIO19_bridges)C++14
100 / 100
1742 ms9724 KiB
#include <iostream>
#include <vector>
#include <algorithm>
#include <ctime>
#include <set>
#include <functional>
#include <cassert>

using namespace std;

const int MAXN = 50007, MAXM = 100007, SPLIT = 320;
struct Edge { int from, to, w, nxt; } edges[MAXM], subEdges[SPLIT * 2 + 7];
int start[MAXN], numEdges;
bool vis[MAXN];
int N, M, Q, ans[MAXM];
vector<pair<int, int>> sortedEdges, changedEdges, tmp;
vector<tuple<int, int, int>> changes, queries;

vector<int> singleChanges[MAXM];
int changePos[MAXM];
bool changed[MAXM];

namespace dsu {
	int arr[MAXN];
	void reset() { fill_n(arr + 1, N, -1); } 
	int root(int u) { return (arr[u] < 0 ? u : arr[u] = root(arr[u])); }
	void join(int u, int v)
	{
		u = root(u), v = root(v);
		if (u == v) return;
		if (arr[u] > arr[v]) swap(u, v);
		arr[u] += arr[v];
		arr[v] = u;
	}
	int sizeOf(int u) { return -arr[root(u)]; }
}

inline void addEdge(int from, int to) {
	subEdges[++numEdges] = {from, to, 0, start[from]};
	start[from] = numEdges;
}

int curAns;
void dfs(int u) {
	curAns += dsu::sizeOf(u);
	vis[u] = true;
	for (int i = start[u]; i > 0; i = subEdges[i].nxt) {
		int v = subEdges[i].to;
		if (!vis[v]) dfs(v);
	}
}

void solve()
{
	dsu::reset();

	for (auto change : changes) {
		int edgeId, newW;
		tie(edgeId, newW, ignore) = change;

		singleChanges[edgeId].push_back(newW);
		changed[edgeId] = true;
	}

	sort(queries.begin(), queries.end(), [&](tuple<int, int, int> &lhs, tuple<int, int, int> &rhs) { return get<1>(lhs) > get<1>(rhs); });
	auto e_it = sortedEdges.rbegin();
	auto c_it = changes.begin();
	for (auto query : queries) {
		int source, w, id;
		tie(source, w, id) = query;
		for (; e_it != sortedEdges.rend() && e_it -> first >= w; ++e_it) if (!changed[e_it -> second]) {
			auto &edge = edges[e_it -> second];
			dsu::join(edge.from, edge.to);
		}

		for (; c_it != changes.end() && get<2>(*c_it) < id; ++c_it) ++changePos[get<0>(*c_it)];
		for (; c_it != changes.begin() && get<2>(*prev(c_it)) > id; --c_it) --changePos[get<0>(*prev(c_it))];

		numEdges = 0;
		for (auto &change : changes) {
			int edgeId = get<0>(change);
			int u = dsu::root(edges[edgeId].from), v = dsu::root(edges[edgeId].to);
			int newW = (changePos[edgeId] ? singleChanges[edgeId][changePos[edgeId] - 1] : edges[edgeId].w);
			if (newW >= w) {
				addEdge(u, v);
				addEdge(v, u);
			}
		}

		curAns = 0;
		dfs(dsu::root(source));
		ans[id] = curAns;

		vis[dsu::root(source)] = 0;
		for (auto change : changes) {
			int edgeId = get<0>(change);
			int u = dsu::root(edges[edgeId].from), v = dsu::root(edges[edgeId].to);
			start[u] = start[v] = 0;
			vis[u] = vis[v] = 0;
		}
	}

	changedEdges.clear();
	for (int edgeId = 1; edgeId <= M; ++edgeId) if (changed[edgeId]) {
		changedEdges.emplace_back(edges[edgeId].w = singleChanges[edgeId].back(), edgeId);
	}
	sort(changedEdges.begin(), changedEdges.end());
	tmp.clear();
	for (auto it1 = changedEdges.begin(), it2 = sortedEdges.begin(); it1 != changedEdges.end() || it2 != sortedEdges.end(); ) {
		for (; it2 != sortedEdges.end() && changed[it2 -> second]; ++it2);
		if (it1 != changedEdges.end() && (it2 == sortedEdges.end() || (*it1) < (*it2))) {
			tmp.push_back(*(it1++));
		} else if (it2 != sortedEdges.end()) {
			tmp.push_back(*(it2++));
		}
	}
	tmp.swap(sortedEdges);

	for (auto change : changes) {
		int edgeId, newW;
		tie(edgeId, newW, ignore) = change;

		singleChanges[edgeId].clear();
		changePos[edgeId] = 0;
		changed[edgeId] = false;
	}

	changes.clear();
	queries.clear();
}

int main()
{
	// freopen("in.txt", "r", stdin);
	// freopen("out.txt", "w", stdout);
	ios_base::sync_with_stdio(0); cin.tie(0);
	cin >> N >> M;
	for (int i = 1; i <= M; ++i) {
		auto &x = edges[i];
		cin >> x.from >> x.to >> x.w;
		sortedEdges.emplace_back(x.w, i);
	}
	sort(sortedEdges.begin(), sortedEdges.end());

	cin >> Q;
	changes.reserve(SPLIT);
	queries.reserve(Q);
	for (int i = 0; i < Q; ++i) {
		int t, x, y;
		cin >> t >> x >> y;
		if (t == 1) changes.emplace_back(x, y, i);
		else queries.emplace_back(x, y, i);

		if (changes.size() == SPLIT) solve();
	}
	solve();

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

	cerr << 1.0 * clock() / CLOCKS_PER_SEC << endl;
}
#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...