Submission #572477

#TimeUsernameProblemLanguageResultExecution timeMemory
572477CpDarkBridges (APIO19_bridges)C++14
0 / 100
3060 ms524288 KiB
#include <bits/stdc++.h>
#define fastInput ios::sync_with_stdio(false); cin.tie(nullptr);

using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ll> vll;
typedef vector<vll> vvll;
typedef pair<int, int> pii;
typedef vector<pii> vp;
typedef vector<vp> vvp;
typedef vector<bool> vb;
typedef vector<vb> vvb;

const int inf = 1e9 + 7;

struct CentroidDecomposition {
	vvp graph;
	vi subSize;
	int n;
	int centroid = -1;

	void init(int N, vvp& g) {
		n = N;
		graph = g;
		subSize.resize(n + 1);
	}

	void dfs(int v, int p) {
		subSize[v] = 1;
		for (int i = 0; i < graph[v].size(); i++) {
			int u = graph[v][i].first;
			if (u != p) {
				dfs(u, v);
				subSize[v] += subSize[u];
			}
		}
	}

	int findCentroid(int v, int p) {
		for (int i = 0; i < graph[v].size(); i++) {
			int u = graph[v][i].first;
			if (u != p && subSize[u] > n / 2) {
				return findCentroid(u, v);
			}
		}
		return v;
	}

	int getCentroid() {
		if (centroid == -1) {
			dfs(1, 1);
			centroid = findCentroid(1, 1);
		}
		return centroid;
	}
};

struct segmentTree {
	vi st;
	int size;

	void init(int n) {
		for (size = 1; size < n; size *= 2) {}
		st.resize(2 * size);
	}

	void update(int index, int val) {
		index += size;
		st[index] = val;
		for (index /= 2; index; index /= 2) {
			st[index] = min(st[index * 2], st[index * 2 + 1]);
		}
	}

	int query(int l, int r) {
		int ans = INT_MAX;
		for (l += size, r += size; l <= r; l /= 2, r /= 2) {
			if (l % 2) {
				ans = min(ans, st[l]);
				l++;
			}
			if (r % 2 == 0) {
				ans = min(ans, st[r]);
				r--;
			}
		}
		return ans;
	}

};

vector<vp> graph;
vll weight;

vb visited;
segmentTree st;

int lastTrue(int s,int k, int lo, int hi) {
	lo--;
	while (lo < hi) {
		int mid = lo + (hi - lo + 1) / 2;
		bool curr = k <= st.query(s, mid);
		if (curr) {
			lo = mid;
		}
		else {
			hi = mid - 1;
		}
	}
	return lo;
}


int firstTrue(int s, int k, int lo, int hi) {
	hi++;
	while (lo < hi) {
		int mid = lo + (hi - lo) / 2;
		bool curr = k <= st.query(mid, s);

		if (curr) {
			hi = mid;
		}
		else {
			lo = mid + 1;
		}
	}
	return lo;
}


inline int findAmount(int root, int k, int n) {
	int ans = 1;
	int left = lastTrue(root, k, root, n - 1);
	ans += left - root + 1;
	int right = firstTrue(root - 1, k, 1, root - 1);
	ans += root - 1 - right + 1;
	return ans;

}

inline void mergeSets(set<pii> &a, set<pii> &b, int w) {
	auto it = b.begin();
	for (int i = 0; i < b.size(); i++) {
		pii curr = *it;
		if (curr.first > w)curr.first = w;
		auto f = a.lower_bound({ curr.first,-1 });
		if (f != a.end() && ((pii)*f).first == curr.first) {
			pii val = { curr.first, curr.second + ((pii)*f).second };
			a.erase(f);
			a.insert(val);
		}
		else {
			a.insert(curr);
		}
		it++;
	}
}
vp bridges;
vp par;
vi depth;
vector<set<pii>> hold;
void dfs(int v, int p, int d, int wp) {
	depth[v] = d;
	par[v] = { p,wp };
	hold[v].insert({ inf,1 });
	for (int i = 0; i < graph[v].size(); i++) {
		int u = graph[v][i].first;
		ll w = weight[graph[v][i].second];
		if (u != p) {
			dfs(u, v, d + 1, graph[v][i].second);
			mergeSets(hold[v], hold[u], w);
		}
	}
}



inline void updatehold(int index) {
	pii edge = bridges[index];
	int upper = edge.first;
	int lower = edge.second;
	if (depth[upper] > depth[lower]) swap(upper, lower);

	int v = lower;
	while (par[v].first != v) {
		v = par[v].first;
		hold[v].clear();
		hold[v].insert({ inf,1 });
		for (int i = 0; i < graph[v].size(); i++) {
			int u = graph[v][i].first;
			ll w = weight[graph[v][i].second];
			if (u != par[v].first) {
				mergeSets(hold[v], hold[u], w);
			}
		}
	}
}


inline int getsub(int v, int w) {
	int ans = 0;
	auto it = hold[v].end();
	it--;

	for (int i = 0; i < hold[v].size(); i++) {
		pii curr = *it;
		if (w > curr.first) return ans;
		ans += curr.second;
		it--;
	}
	return ans;
}

inline int maxReach(int v, int w) {
	if (v == par[v].first)return v;
	if (w <= weight[par[v].second]) {
		return maxReach(par[v].first, w);
	}
	return v;
}


inline int queryCount(int s, int w) {
	int p = maxReach(s, w);
	int pc = getsub(p, w);
	int sc = getsub(s, w);
	if (p == par[s].first) sc = 1;

	int ans = pc - sc + 1;
	return ans;
}

int main() {
	fastInput;
	int n, m;
	cin >> n >> m;

	//st.init(n);
	graph.resize(n + 1);
	weight.resize(m + 1);
	bridges.resize(m + 1);
	par.resize(n + 1);
	depth.resize(n + 1);
	hold.resize(n + 1);
	int a, b, d;
	for (int i = 1; i <= m; i++) {
		cin >> a >> b >> d;
		graph[a].push_back({ b,i });
		graph[b].push_back({ a,i });
		bridges[i] = { a,b };
		weight[i] = d;
		//st.update(i, d);
	}
	CentroidDecomposition cd;
	cd.init(n + 1, graph);
	int root = cd.getCentroid();
	dfs(root, root, 1, -1);

	int q;
	cin >> q;
	int t;
	for (int i = 0; i < q; i++) {
		cin >> t;
		if (t == 1) {
			 int r;
			 cin >> b >> r;
			 weight[b] = r;
			 updatehold(b);
		}
		else {
			int s, w;
			cin >> s >> w;
			int ans = queryCount(s, w);
			cout << ans << endl;
		}
	}


	return 0;
}

Compilation message (stderr)

bridges.cpp: In member function 'void CentroidDecomposition::dfs(int, int)':
bridges.cpp:32:21: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   32 |   for (int i = 0; i < graph[v].size(); i++) {
      |                   ~~^~~~~~~~~~~~~~~~~
bridges.cpp: In member function 'int CentroidDecomposition::findCentroid(int, int)':
bridges.cpp:42:21: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   42 |   for (int i = 0; i < graph[v].size(); i++) {
      |                   ~~^~~~~~~~~~~~~~~~~
bridges.cpp: In function 'void mergeSets(std::set<std::pair<int, int> >&, std::set<std::pair<int, int> >&, int)':
bridges.cpp:145:20: warning: comparison of integer expressions of different signedness: 'int' and 'std::set<std::pair<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  145 |  for (int i = 0; i < b.size(); i++) {
      |                  ~~^~~~~~~~~~
bridges.cpp: In function 'void dfs(int, int, int, int)':
bridges.cpp:168:20: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  168 |  for (int i = 0; i < graph[v].size(); i++) {
      |                  ~~^~~~~~~~~~~~~~~~~
bridges.cpp: In function 'void updatehold(int)':
bridges.cpp:191:21: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  191 |   for (int i = 0; i < graph[v].size(); i++) {
      |                   ~~^~~~~~~~~~~~~~~~~
bridges.cpp: In function 'int getsub(int, int)':
bridges.cpp:207:20: warning: comparison of integer expressions of different signedness: 'int' and 'std::set<std::pair<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  207 |  for (int i = 0; i < hold[v].size(); i++) {
      |                  ~~^~~~~~~~~~~~~~~~
#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...