QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#431507#6847. Hide-And-Seek Gameucup-team3591#AC ✓195ms3836kbC++203.2kb2024-06-05 17:35:352024-06-05 17:35:36

Judging History

你现在查看的是最新测评结果

  • [2024-06-05 17:35:36]
  • 评测
  • 测评结果:AC
  • 用时:195ms
  • 内存:3836kb
  • [2024-06-05 17:35:35]
  • 提交

answer

// Code by Heratino & Nelofus

#include <bits/stdc++.h>
using i64 = long long;

template<typename T>
inline void chkmin(T &a, const T &b) {if (a > b)	a = b;}
constexpr int N = 3e3 + 10;
constexpr i64 inf = 1e18;
std::basic_string<int> G[N];
int dep[N];
int fa[15][N];
int n, m;
inline void add(int u, int v) {G[u].push_back(v);}

void exgcd(i64 a, i64 b, i64 &x, i64 &y, i64 &d) {
	if (b == 0) {
		d = a, x = 1, y = 0;
	} else {
		exgcd(b, a % b, y, x, d);
		y -= a / b * x;
	}
}

void dfs(int u) {
	dep[u] = dep[fa[0][u]] + 1;
	for (const int &v : G[u]) {
		if (v == fa[0][u])
			continue;
		fa[0][v] = u;
		dfs(v);
	}
}

void clear() {
	for (int i = 1; i <= n; i++) {
		G[i].clear(), dep[i] = 0;
		for (int j = 0; j < 15; j++)
			fa[j][i] = 0;
	}
}

inline int LCA(int u, int v) {
	if (dep[u] < dep[v])
		std::swap(u, v);
	for (int k = 14; k >= 0; k--)
		if (dep[fa[k][u]] >= dep[v])
			u = fa[k][u];
	if (u == v)
		return u;
	for (int k = 14; k >= 0; k--)
		if (fa[k][u] != fa[k][v])
			u = fa[k][u], v = fa[k][v];
	return fa[0][u];
}
inline int llen(int u, int v) {
	int lca = LCA(u, v);
	return dep[u] + dep[v] - 2 * dep[lca];
}

void solve() {
	std::cin >> n >> m;
	clear();
	for (int i = 1; i < n; i++) {
		int u, v;
		std::cin >> u >> v;
		add(u, v), add(v, u);
	}
	dfs(1);

	for (int k = 1; k < 15; k++)
		for (int i = 1; i <= n; i++)
			fa[k][i] = fa[k - 1][fa[k - 1][i]];

	auto find = [&](int x, int y, std::set<int> &st) {
		st.insert(y);
		while (dep[x] > dep[y]) {
			st.insert(x);
			x = fa[0][x];
		}
	};

	while (m--) {
		i64 ans = -1;
		i64 t = inf;
		int sa, ta, sb, tb;
		std::cin >> sa >> ta >> sb >> tb;

		int alca = LCA(sa, ta), blca = LCA(sb, tb);

		std::set<int> l1, l2;
		find(sa, alca, l1);
		find(ta, alca, l1);
		find(sb, blca, l2);
		find(tb, blca, l2);

		int len1 = llen(sa, ta), len2 = llen(sb, tb);
		auto upd = [&](int p, i64 ct) {
			if (ct < t)
				t = ct, ans = p;
		};

		auto sol = [&](int u) {
			std::array<int, 2> p = {llen(u, sa), llen(u, ta)};
			std::array<int, 2> q = {llen(u, sb), llen(u, tb)};
			for (int i = 0; i < 2; i++) {
				for (int j = 0; j < 2; j++) {
					i64 x, y, pgcd;
					i64 a = 2 * len1, b = p[i] + len1 * i;
					i64 c = 2 * len2, d = q[j] + len2 * j;

					// ax + b = cy + d
					// ax - cy = d - b
					if (d == b) {
						// ax = by = lca(a, c)
						upd(u, b);
						continue;
					}
					exgcd(a, c, x, y, pgcd);

					y = -y;
					if ((d - b) % pgcd != 0)
						continue;
					// 求 x 的最小整数解
					// 不能加 abs 。在负数里面处理是完全可行的。
					i64 mul = (d - b) / pgcd;
					x *= mul;

					i64 step = c / pgcd;

					x = (x % step + step) % step;
					y = (d - b - a * x) / (-c);

					// 显然圈数 >= 0
					if (y >= 0)
						upd(u, a * x + b);
				}
			}
		};

		for (const int &u : l1) {
			if (l2.find(u) != l2.end()) {
				sol(u);
			}
		}
		std::cout << ans << '\n';
	}
}

int main() {
#ifdef HeratinoNelofus
	freopen("input.txt", "r", stdin);
#endif
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);

	int T;
	std::cin >> T;
	while (T--) {
		solve();
	}
	return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 195ms
memory: 3836kb

input:

500
6 20
1 2
1 3
3 4
2 5
3 6
1 6 6 5
2 1 6 2
5 1 2 6
2 6 1 2
6 3 6 4
4 1 1 3
5 6 3 4
2 1 3 5
2 4 1 2
6 2 1 2
6 2 1 4
1 6 1 6
2 5 2 6
2 5 6 2
5 2 1 3
5 6 6 4
4 1 4 5
5 4 4 1
3 6 1 2
6 1 4 3
71 30
1 2
2 3
2 4
4 5
2 6
6 7
4 8
2 9
1 10
9 11
3 12
5 13
5 14
10 15
6 16
13 17
17 18
4 19
5 20
17 21
20 22
4 2...

output:

3
-1
-1
-1
6
3
-1
1
-1
1
3
1
2
-1
-1
3
4
1
-1
3
-1
11
2
-1
5
-1
17
-1
-1
5
-1
-1
-1
-1
2
-1
5
53
5
7
-1
-1
2
4
-1
-1
-1
-1
-1
-1
-1
5
-1
1
5
1
-1
-1
-1
-1
33
5
1
1
-1
1
-1
-1
-1
-1
7
-1
-1
9
5
3
-1
-1
-1
19
-1
-1
6
5
-1
-1
5
-1
-1
-1
-1
1
-1
7
-1
-1
1
-1
-1
-1
8
-1
13
-1
-1
-1
-1
4
5
-1
-1
5
-1
-1
8...

result:

ok 53199 lines