結果

問題 No.2491 Pochi and A Warp Machine
ユーザー square1001square1001
提出日時 2023-09-29 22:53:43
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
WA  
実行時間 -
コード長 5,985 bytes
コンパイル時間 3,646 ms
コンパイル使用メモリ 242,076 KB
実行使用メモリ 89,096 KB
最終ジャッジ日時 2024-07-22 16:52:05
合計ジャッジ時間 12,784 ms
ジャッジサーバーID
(参考情報)
judge5 / judge4
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
13,888 KB
testcase_01 AC 2 ms
6,940 KB
testcase_02 WA -
testcase_03 AC 2 ms
6,940 KB
testcase_04 WA -
testcase_05 WA -
testcase_06 WA -
testcase_07 WA -
testcase_08 WA -
testcase_09 WA -
testcase_10 WA -
testcase_11 WA -
testcase_12 WA -
testcase_13 WA -
testcase_14 WA -
testcase_15 WA -
testcase_16 WA -
testcase_17 WA -
testcase_18 WA -
testcase_19 TLE -
testcase_20 -- -
testcase_21 -- -
testcase_22 -- -
testcase_23 -- -
testcase_24 -- -
testcase_25 -- -
testcase_26 -- -
testcase_27 -- -
testcase_28 -- -
testcase_29 -- -
testcase_30 -- -
testcase_31 -- -
testcase_32 -- -
testcase_33 -- -
testcase_34 -- -
testcase_35 -- -
testcase_36 -- -
testcase_37 -- -
testcase_38 -- -
testcase_39 -- -
testcase_40 -- -
testcase_41 -- -
testcase_42 -- -
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <bits/stdc++.h>
using namespace std;

const int INF = 1012345678;

struct edge {
	int va, vb;
};

struct state {
	int depth, current, bottom;
};

string to_string(const vector<int>& arr) {
	string res = "[";
	for (int i = 0; i < arr.size(); i++) {
		if (i != 0) {
			res += ", ";
		}
		res += to_string(arr[i]);
	}
	res += "]";
	return res;
}

class fenwicktree {
private:
	int n;
	map<int, long long> d;
	long long rangesum(int r) {
		long long ans = 0;
		for (int i = r; i >= 1; i -= i & (-i)) {
			ans += d[i];
		}
		return ans;
	}
public:
	fenwicktree() : n(0), d(map<int, long long>()) {}
	fenwicktree(int n_) : n(n_), d(map<int, long long>()) {}
	void add(int pos, long long x) {
		for (int i = pos + 1; i <= n; i += i & (-i)) {
			d[i] += x;
		}
	}
	long long rangesum(int l, int r) {
		if (l >= r) {
			return 0;
		}
		return rangesum(r) - rangesum(l);
	}
};

void solve(int N, const vector<int>& P, const vector<edge>& E, const vector<int>& dlist, vector<long long>& ans) {
	// step #1. make graph
	vector<vector<int> > G(N);
	for (edge e : E) {
		G[e.va].push_back(e.vb);
		G[e.vb].push_back(e.va);
	}

	// step #2. find centroid
	int root = -1;
	vector<int> subsize(N, 1);
	auto find_centroid = [&](auto& self, int pos, int pre) -> void {
		bool flag = true;
		for (int i : G[pos]) {
			if (i != pre) {
				self(self, i, pos);
				subsize[pos] += subsize[i];
				if (subsize[i] * 2 > N) {
					flag = false;
				}
			}
		}
		if (flag && subsize[pos] * 2 >= N) {
			root = pos;
		}
	};
	find_centroid(find_centroid, 0, -1);

	// step #3. build tree
	vector<int> depth(N);
	vector<int> comp(N, -1);
	vector<vector<int> > child(N);
	auto build_tree = [&](auto& self, int pos, int pre) -> void {
		for (int i : G[pos]) {
			if (i != pre) {
				comp[i] = comp[pos];
				depth[i] = depth[pos] + 1;
				child[pos].push_back(i);
				self(self, i, pos);
			}
		}
	};
	int K = G[root].size();
	child[root] = G[root];
	for (int i = 0; i < K; i++) {
		comp[G[root][i]] = i;
		depth[G[root][i]] = 1;
		build_tree(build_tree, G[root][i], root);
	}

	// step #5. calculate answer passing root
	vector<int> ord(N);
	for (int i = 0; i < N; i++) {
		ord[i] = i;
	}
	sort(ord.begin(), ord.end(), [&](int va, int vb) {
		return P[va] > P[vb];
	});
	// cerr << "N = " << N << endl;
	// cerr << "centroid = " << root << endl;
	vector<fenwicktree> bit0(K + 1, fenwicktree(N));
	vector<fenwicktree> bit1(K + 1, fenwicktree(N));
	for (int i : ord) {
		int idx = P[i];
		// cost1: dlist[target_idx - 1]
		// cost2: 1 + depth[i] + depth[target]
		// if dlist[target_idx - 1] - depth[target] - 1 >= depth[i], profit
		long long profit = 0;
		profit += bit1[K].rangesum(depth[i], N);
		profit -= bit0[K].rangesum(depth[i], N) * depth[i];
		if (i != root) {
			profit -= bit1[comp[i]].rangesum(depth[i], N);
			profit += bit0[comp[i]].rangesum(depth[i], N) * depth[i];
		}
		ans[idx] -= profit;
		int diff = (idx != 0 ? dlist[idx - 1] : 0) - depth[i] - 1;
		// cerr << "i = " << i << ": profit = " << profit << ", diff = " << diff << endl;
		if (diff >= 0) {
			bit0[K].add(diff, 1);
			bit1[K].add(diff, diff);
			if (i != root) {
				bit0[comp[i]].add(diff, 1);
				bit1[comp[i]].add(diff, diff);
			}
		}
	}

	// step #6. divide into subproblems
	vector<vector<int> > subcomp(K);
	for (int i = 0; i < N; i++) {
		if (i != root) {
			subcomp[comp[i]].push_back(i);
		}
	}
	vector<vector<int> > subp(K);
	vector<vector<edge> > sube(K);
	for (int i = 0; i < K; i++) {
		subp[i].resize(subcomp[i].size());
		for (int j = 0; j < subcomp[i].size(); j++) {
			subp[i][j] = P[subcomp[i][j]];
		}
	}
	for (int i = 0; i < N - 1; i++) {
		if (comp[E[i].va] == comp[E[i].vb]) {
			int id = comp[E[i].va];
			int nva = lower_bound(subcomp[id].begin(), subcomp[id].end(), E[i].va) - subcomp[id].begin();
			int nvb = lower_bound(subcomp[id].begin(), subcomp[id].end(), E[i].vb) - subcomp[id].begin();
			sube[id].push_back(edge{nva, nvb});
		}
	}
	for (int i = 0; i < K; i++) {
		solve(subcomp[i].size(), subp[i], sube[i], dlist, ans);
	}
}

vector<int> distances(int N, const vector<edge>& E, const vector<int>& S, const vector<int>& T) {
	vector<vector<int> > G(N);
	for (edge e : E) {
		G[e.va].push_back(e.vb);
		G[e.vb].push_back(e.va);
	}
	vector<int> par(N);
	vector<int> depth(N);
	auto build_tree = [&](auto& self, int pos, int pre) -> void {
		for (int i : G[pos]) {
			if (i != pre) {
				par[i] = pos;
				depth[i] = depth[pos] + 1;
				self(self, i, pos);
			}
		}
	};
	build_tree(build_tree, 0, -1);
	int bits = (N >= 3 ? 32 - __builtin_clz(N - 1) : N);
	vector<vector<int> > spar(bits);
	spar[0] = par;
	spar[0][0] = 0;
	for (int i = 1; i < bits; i++) {
		spar[i].resize(N);
		for (int j = 0; j < N; j++) {
			spar[i][j] = spar[i - 1][spar[i - 1][j]];
		}
	}
	auto lca = [&](int va, int vb) {
		if (depth[va] < depth[vb]) {
			swap(va, vb);
		}
		int d = depth[va] - depth[vb];
		for (int i = 0; i < bits; i++) {
			if ((d >> i) & 1) {
				va = spar[i][va];
			}
		}
		if (va == vb) {
			return va;
		}
		for (int i = bits - 1; i >= 0; i--) {
			if (spar[i][va] != spar[i][vb]) {
				va = spar[i][va];
				vb = spar[i][vb];
			}
		}
		return spar[0][va];
	};
	vector<int> ans(S.size());
	for (int i = 0; i < S.size(); i++) {
		ans[i] = depth[S[i]] + depth[T[i]] - depth[lca(S[i], T[i])] * 2;
		// cerr << "N = " << N << ", S = " << S[i] << ", T = " << T[i] << ", ans = " << ans[i] << endl;
	}
	return ans;
}

int main() {
	cin.tie(0);
	ios::sync_with_stdio(false);
	int N;
	cin >> N;
	vector<edge> E(N - 1);
	for (int i = 0; i < N - 1; i++) {
		cin >> E[i].va >> E[i].vb;
		E[i].va -= 1;
		E[i].vb -= 1;
	}
	vector<int> P(N), A(N - 1), B(N - 1);
	for (int i = 0; i < N; i++) {
		P[i] = i;
		if (i != N - 1) {
			A[i] = i;
			B[i] = i + 1;
		}
	}
	vector<int> D = distances(N, E, A, B);
	long long dsum = 0;
	for (int i = 0; i < N - 1; i++) {
		dsum += D[i];
	}
	vector<long long> ans(N, dsum);
	solve(N, P, E, D, ans);
	for (int i = 0; i < N; i++) {
		cout << ans[i] << '\n';
	}
	return 0;
}
0