제출 #660377

#제출 시각아이디문제언어결과실행 시간메모리
660377GusterGoose27다리 (APIO19_bridges)C++11
60 / 100
2963 ms11892 KiB
#include <bits/stdc++.h>

using namespace std;

const int MAXN = 50000;
const int MAXM = 1e5;
int n, m, q;

class edge {
public:
	int x, y, w;
	edge() {}
	edge(int x, int y, int w) : x(x), y(y), w(w) {}
};

class update {
public:
	bool type; // 0 = update, 1 = query
	int a, b; // two variables
	update() {}
	update(bool t, int a, int b) : type(t), a(a), b(b) {}
};

class query {
public:
	int s, w, i;
	query(int s, int w, int i) : s(s), w(w), i(i) {}
};

bool operator<(query &a, query &b) {
	return (a.w > b.w);
}

bool operator<(edge &a, edge &b) {
	return (a.w == b.w) ? ((a.x == b.x) ? (a.y < b.y) : (a.x < b.x)) : (a.w > b.w);
}

edge edge_list[MAXM];

struct comp {
	bool operator()(const int &a, const int &b) const {
		return edge_list[a] < edge_list[b];
	}
};

set<int, comp> edges;
int adj_w[MAXM];
bool vis[MAXN];
vector<int> un_vis;
vector<int> uf_edges[MAXN];
int uf[MAXN];
int rnk[MAXN];
int sz[MAXN];
int block_sz;
int block_cnt;
update updates[MAXM];
int ans[MAXM];

int find(int i) {
	return (uf[i] == -1) ? i : (uf[i] = find(uf[i]));
}

void merge(int a, int b) {
	a = find(a);
	b = find(b);
	if (a != b) {
		if (rnk[a] < rnk[b]) swap(a, b);
		uf[b] = a;
		sz[a] += sz[b];
		if (rnk[a] == rnk[b]) rnk[a]++;
	}
}

int dfs(int cur) {
	vis[cur] = 1;
	un_vis.push_back(cur);
	int s = sz[cur];
	for (int nxt: uf_edges[cur]) {
		if (!vis[nxt]) s += dfs(nxt);
	}
	return s;
}

int main() {
	ios_base::sync_with_stdio(false); cin.tie(NULL);
	cin >> n >> m;
	for (int i = 0; i < m; i++) {
		int x, y, w; cin >> x >> y >> w;
		x--; y--;
		edge_list[i] = edge(x, y, w);
		edges.insert(i);
	}
	cin >> q;
	for (int i = 0; i < q; i++) {
		int t; int a, b;
		cin >> t >> a >> b;
		a--;
		updates[i] = update(t-1, a, b);
	}
	block_sz = 1+(int)sqrt(q);
	block_cnt = (q+block_sz-1)/(block_sz);
	assert(block_sz*block_cnt >= q);
	for (int i = 0; i < block_cnt; i++) {
		fill(uf, uf+n, -1);
		fill(sz, sz+n, 1);
		memset(rnk, 0, sizeof(int)*n);
		int s = block_sz*i;
		int e = min(block_sz*(i+1), q);
		vector<query> queries; // weight, start
		vector<int> ext_edges;
		for (int j = s; j < e; j++) {
			if (updates[j].type) queries.push_back(query(updates[j].a, updates[j].b, j));
			else {
				if (edges.find(updates[j].a) != edges.end()) {
					ext_edges.push_back(updates[j].a);
					edges.erase(updates[j].a);
				}
			}
		}
		sort(queries.begin(), queries.end());
		auto e_pos = edges.begin();
		for (query p: queries) {
			while (e_pos != edges.end() && edge_list[*e_pos].w >= p.w) {
				merge(edge_list[*e_pos].x, edge_list[*e_pos].y);
				e_pos++;
			}
			for (int v: ext_edges) {
				adj_w[v] = edge_list[v].w;
			}
			for (int j = s; j < p.i; j++) {
				if (updates[j].type) continue;
				adj_w[updates[j].a] = updates[j].b;
			}
			for (int v: ext_edges) {
				if (adj_w[v] >= p.w) {
					int x = find(edge_list[v].x);
					int y = find(edge_list[v].y);
					uf_edges[x].push_back(y);
					uf_edges[y].push_back(x);
				}
			}
			ans[p.i] = dfs(find(p.s));
			for (int v: ext_edges) {
				if (adj_w[v] >= p.w) {
					int x = find(edge_list[v].x);
					int y = find(edge_list[v].y);
					uf_edges[x].clear();
					uf_edges[y].clear();
				}
			}
			for (int v: un_vis) vis[v] = 0;
			un_vis.clear();
		}
		for (int j = e-1; j >= s; j--) {
			if (!updates[j].type && edges.find(updates[j].a) == edges.end()) {
				edge_list[updates[j].a].w = updates[j].b;
				edges.insert(updates[j].a);
			}
		}
	}
	for (int i = 0; i < q; i++) {
		if (updates[i].type) {
			cout << ans[i] << "\n";
			assert(ans[i] != 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...