Submission #165058

#TimeUsernameProblemLanguageResultExecution timeMemory
165058YuzuChanFactories (JOI14_factories)C++14
100 / 100
3251 ms394472 KiB
#pragma GCC optimize("O3")

#include <factories.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cassert>
#include <cstring>
#include <numeric>
#include <set>
#include <queue>

#define sz(a) (int)((a).size())
#define all(a) (a).begin(), (a).end()
#define pb push_back

using namespace std;
using ll = long long;
using vi = vector<int>;
using pii = pair<int, int>;

const int LG = 20;
const int N = 1000228;
const ll inf = 1e18;

int n;
vector<vector<pii>> g;
vi in, out;
int timer;
vector<ll> dep;
vector<bool> in_A1, in_A2;
int lg[N];
pair<ll, int> sparse[LG][N];
vi A;
vector<vector<pair<int, ll>>> ga;
vector<ll> dp;
ll ans;

void dfs(int v, int p) {
	sparse[0][timer] = { dep[v], v };
	in[v] = timer++;
	out[v] = in[v];
	for (auto e : g[v]) {
		if (e.first != p) {
			dep[e.first] = dep[v] + e.second;
			dfs(e.first, v);
			sparse[0][timer] = { dep[v], v };
			out[v] = timer++;
		}
	}
}

void Init(int _n, int _u[], int _v[], int _w[]) {
	n = _n;
	g.resize(n);
	for (int i = 0; i < n - 1; i++) {
		g[_u[i]].pb({ _v[i], _w[i] });
		g[_v[i]].pb({ _u[i], _w[i] });
	}
	dep.resize(n);
	in.resize(n);
	out.resize(n);
	dfs(0, -1);
	for (int i = 2; i < N; i++) {
		lg[i] = 1 + lg[i >> 1];
	}
	for (int j = 1; j < LG; j++) {
		for (int i = 0; i + (1 << j) - 1 < timer; i++) {
			sparse[j][i] = min(sparse[j - 1][i], sparse[j - 1][i + (1 << (j - 1))]);
		}
	}
	in_A1.resize(n, false);
	in_A2.resize(n, false);
}

bool upper(int u, int v) {
	return (in[u] <= in[v] && out[v] <= out[u]);
}

int LCA(int u, int v) {
	u = out[u];
	v = out[v];
	if (u > v) {
		swap(u, v);
	}
	int l = lg[v - u + 1];
	return min(sparse[l][u], sparse[l][v - (1 << l) + 1]).second;
}

void dfs_dp(int v) {
	if (in_A2[A[v]]) {
		dp[v] = 0;
	}
	for (auto e : ga[v]) {
		dfs_dp(e.first);
		dp[v] = min(dp[v], dp[e.first] + e.second);
	}
}

void dfs_upd(int v, ll dp_up) {
	if (in_A1[A[v]]) {
		ans = min(ans, min(dp[v], dp_up));
	}
	vector<ll> suf_min(sz(ga[v]) + 1);
	suf_min.back() = inf;
	for (int i = sz(ga[v]) - 1; i >= 0; i--) {
		suf_min[i] = min(suf_min[i + 1], dp[ga[v][i].first] + ga[v][i].second);
	}
	ll pref_min = inf;
	for (int i = 0; i < sz(ga[v]); i++) {
		dfs_upd(ga[v][i].first, min({ pref_min, suf_min[i + 1], dp_up, in_A2[A[v]] ? 0 : inf }) + ga[v][i].second);
		pref_min = min(pref_min, dp[ga[v][i].first] + ga[v][i].second);
	}
}

ll Query(int n1, int _A1[], int n2, int _A2[]) {
	A.clear();
	A.resize(n1 + n2);
	for (int i = 0; i < n1; i++) {
		A[i] = _A1[i];
		in_A1[_A1[i]] = true;
	}
	for (int i = 0; i < n2; i++) {
		A[i + n1] = _A2[i];
		in_A2[_A2[i]] = true;
	}
	sort(all(A), [](int u, int v) { return in[u] < in[v]; });
	for (int i = sz(A) - 2; i >= 0; i--) {
		A.pb(LCA(A[i], A[i + 1]));
	}
	sort(all(A), [](int u, int v) { return in[u] < in[v]; });
	A.resize(unique(all(A)) - A.begin());
	ga.clear();
	ga.resize(sz(A));
	vi st;
	int edge_check = 0;
	for (int i = 0; i < sz(A); i++) {
		while (!st.empty() && !upper(A[st.back()], A[i])) {
			st.pop_back();
		}
		if (!st.empty()) {
			ga[st.back()].pb({ i, dep[A[i]] - dep[A[st.back()]] });
			edge_check++;
		}
		st.pb(i);
	}
	assert(edge_check == sz(A) - 1);
	dp.assign(sz(A), inf);
	dfs_dp(0);
	ans = inf;
	dfs_upd(0, inf);
	for (int i = 0; i < n1; i++) {
		in_A1[_A1[i]] = false;
	}
	for (int i = 0; i < n2; i++) {
		in_A2[_A2[i]] = false;
	}
	return ans;
}
/*
int u[100], v[100], w[100];
int A1[100], A2[100];

int32_t main() {
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int n, q;
	cin >> n >> q;
	for (int i = 0; i < n - 1; i++) {
		cin >> u[i] >> v[i] >> w[i];
	}
	Init(n, u, v, w);
	while (q--) {
		int n1, n2;
		cin >> n1 >> n2;
		for (int i = 0; i < n1; i++) {
			cin >> A1[i];
		}
		for (int i = 0; i < n2; i++) {
			cin >> A2[i];
		}
		cout << Query(n1, A1, n2, A2) << endl;
	}
}
*/
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...