Submission #402700

#TimeUsernameProblemLanguageResultExecution timeMemory
402700atoizBridges (APIO19_bridges)C++14
100 / 100
2953 ms7796 KiB
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <cassert>
#include <numeric>

using namespace std;

const int N = 50007, M = 100007, Q = 100007, K = 300;
int n, sm, m, sq, q;
struct bridge_t { int u, v, st, en, d; } bridges[M + Q], candidates[K * 3 + 100];
struct query_t { int t, a, b, res; } queries[Q];
struct edge_t { int to, nxt; } edges[K * 6 + 100];
int head[K * 6 + 100], dsu[N], mapping[N], cnt[K * 6 + 100], stk[K * 6 + 100];
bool vis[K * 6 + 100];
bool in_mst[M + Q];

int root(int u) { return dsu[u] < 0 ? u : dsu[u] = root(dsu[u]); }
bool same(int u, int v) { return root(u) == root(v); }
void join(int u, int v) {
	u = root(u), v = root(v);
	if (u == v) return;
	if (dsu[u] > dsu[v]) swap(u, v);
	dsu[u] += dsu[v], dsu[v] = u;
}
int get_cnt(int u) { return -dsu[root(u)]; }

void solve(int qs, int qe) {
	memset(in_mst, 0, sizeof(in_mst[0]) * (m + 1));
	int c = 0, st = queries[qs].t, en = queries[qe - 1].t + 1;

	memset(dsu, -1, sizeof(dsu[0]) * (n + 1));
	for (int i = 1; i <= m; ++i) {
		bridge_t b = bridges[i];
		if (en <= b.st || b.en <= st) continue;
		if (not same(b.u, b.v)) {
			join(b.u, b.v);
			if (b.st <= st && en <= b.en) {
				in_mst[i] = true;
			}
		}
	}

	memset(dsu, -1, sizeof(dsu[0]) * (n + 1));
	for (int i = 1; i <= m; ++i) {
		bridge_t b = bridges[i];
		// int pc = c;
		if (en <= b.st || b.en <= st) continue;
		if (not same(b.u, b.v)) {
			if (b.st > st || en > b.en) {
				candidates[++c] = b;
			} else {
				join(b.u, b.v);
				if (!in_mst[i]) {
					candidates[++c] = b;
				}
			}
		}
		// cout << b.u << ' ' << b.v << ' ' << b.st << ' ' << b.en << ' ' << b.d << ": ";
		// if (pc < c) cout << 'c';
		// else if (in_mst[i]) cout << "i";
		// else cout << "-";
		// cout << endl;
	}

	vector<int> qis(qe - qs);
	iota(qis.begin(), qis.end(), qs);
	sort(qis.begin(), qis.end(), [&](int qi, int qj) {
		return queries[qi].b > queries[qj].b;
	});

	memset(dsu, -1, sizeof(dsu[0]) * (n + 1));
	int bi = 1;
	for (int qi : qis) {
		query_t &curq = queries[qi];
		for (; bi <= m && bridges[bi].d >= curq.b; ++bi) {
			if (in_mst[bi]) {
				join(bridges[bi].u, bridges[bi].v);
			}
		}

		int nv = 0, ne = 0;
		// cout << "q " << curq.t << ' ' << curq.a << ' ' << curq.b << " -> " << curq.res << endl;
		for (int ci = 1; ci <= c && candidates[ci].d >= curq.b; ++ci) {
			if (curq.t < candidates[ci].st || candidates[ci].en <= curq.t) continue;
			int u = root(candidates[ci].u), v = root(candidates[ci].v);
			if (u == v) continue;
			if (!mapping[u]) mapping[u] = ++nv, head[nv] = 0, vis[nv] = false, cnt[nv] = get_cnt(u);
			if (!mapping[v]) mapping[v] = ++nv, head[nv] = 0, vis[nv] = false, cnt[nv] = get_cnt(v);
			u = mapping[u], v = mapping[v];

			edges[++ne] = {v, head[u]}, head[u] = ne;
			edges[++ne] = {u, head[v]}, head[v] = ne;
		}

		// for (int u = 1; u <= n; ++u) cout << mapping[u] << ' '; cout << endl;
		int ns = 0;
		stk[++ns] = mapping[root(curq.a)];
		if (stk[ns]) {
			vis[stk[ns]] = true;

			while (ns) {
				int u = stk[ns--];
				// cout << u << ": " << cnt[u] << endl;
				curq.res += cnt[u];
				for (int i = head[u]; i; i = edges[i].nxt) {
					int v = edges[i].to;
					if (!vis[v]) vis[stk[++ns] = v] = true;
				}
			}
		} else {
			curq.res = get_cnt(curq.a);
		}

		for (int ci = 1; ci <= c && candidates[ci].d >= curq.b; ++ci) {
			if (curq.t < candidates[ci].st || candidates[ci].en <= curq.t) continue;
			int u = root(candidates[ci].u), v = root(candidates[ci].v);
			if (u == v) continue;
			mapping[u] = 0;
			mapping[v] = 0;
		}
	}
}	

int main() {
	scanf("%d %d", &n, &sm);
	for (int i = 1; i <= sm; ++i) {
		scanf("%d %d %d", &bridges[i].u, &bridges[i].v, &bridges[i].d);
	}
	scanf("%d", &sq);
	m = sm, q = 0;
	for (int t = 1; t <= sq; ++t) {
		int k, a, b;
		scanf("%d %d %d", &k, &a, &b);
		if (k == 1) {
			bridges[++m] = bridges[a];
			bridges[a].st = bridges[m].en = t;
			bridges[a].d = b;
		} else {
			queries[++q] = {t, a, b, 0};
		}
	}
	for (int i = 1; i <= sm; ++i) bridges[i].en = sq + 1;

	sort(bridges + 1, bridges + m + 1, [&](const bridge_t &lhs, const bridge_t &rhs) {
		return lhs.d > rhs.d;
	});

	for (int st = 1, en = st; st <= q; st = en) {
		for (en = st; en <= q && queries[en].t - queries[st].t - en + st <= K; ++en);
		solve(st, en);
	}

	for (int t = 1; t <= q; ++t) {
		printf("%d\n", queries[t].res);
	}
	fprintf(stderr, "%.3f\n", 1.0 * clock() / CLOCKS_PER_SEC);
}

Compilation message (stderr)

bridges.cpp: In function 'int main()':
bridges.cpp:130:7: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  130 |  scanf("%d %d", &n, &sm);
      |  ~~~~~^~~~~~~~~~~~~~~~~~
bridges.cpp:132:8: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  132 |   scanf("%d %d %d", &bridges[i].u, &bridges[i].v, &bridges[i].d);
      |   ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bridges.cpp:134:7: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  134 |  scanf("%d", &sq);
      |  ~~~~~^~~~~~~~~~~
bridges.cpp:138:8: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  138 |   scanf("%d %d %d", &k, &a, &b);
      |   ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
#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...