#include<bits/stdc++.h> usingnamespace std; #define ll long long constint INF = 0x3f3f3f3f; constint N = 2e6 + 10; const ll mod = 1e9 + 7; int n, m; typedef pair<int, int>pii; int cnt[N]; vector<pii>vc; int ans = INF; intmain(){ scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) { int k, x; scanf("%d", &k); for (int j = 0; j < k; j++) { scanf("%d", &x); vc.push_back(pii(x, i)); } } sort(vc.begin(), vc.end()); int p = 0, tmp = 0; for (int i = 0; i < (int)vc.size(); i++) { while (p != vc.size() && tmp < m) { int x = vc[p].second; cnt[x]++; if (cnt[x] == 1)tmp++; p++; } if (tmp == m)ans = min(ans, vc[p - 1].first - vc[i].first); int x = vc[i].second; cnt[x]--; if (!cnt[x])tmp--; } printf("%d\n", ans); return0; }
K - The Flee Plan of Groundhog
题意:给定一棵树,A 先从 1 向 n 移动 t 个点,B 这时从 n 开始以一秒 2 点 的速度追 A,B开始以 一秒 1 点的速度逃跑,问最多多久追上。
服了,搞自己有一手的。
如果开始追的时候 A 就在 n,则时间为 0 !!
设开始追时 A 在点 u。
做法一:先处理出以 n 为根时各点深度,再处理出以 u 为根时个点深度,再从小到大枚举时间,可以得到与 u 距离 i 的所有点,如果 n 到这些点距离更小,则说明会被追上,则不能再继续枚举。对于所有被枚举到的点,用它与 n 的距离更新答案。
#include<bits/stdc++.h> usingnamespace std; #define ll long long constint INF = 0x3f3f3f3f; constint N = 2e6 + 10; const ll mod = 998244353; int n, t; vector<int>G[N]; int d1[N], fa[N], d2[N]; voiddfs(int u, int _fa){ fa[u] = _fa; for (int v : G[u]) { if (v == _fa)continue; d1[v] = d1[u] + 1; dfs(v, u); } } voiddfs2(int u, int _fa){ for (int v : G[u]) { if (v == _fa)continue; d2[v] = d2[u] + 1; dfs2(v, u); } } vector<int>vc[N]; intmain(){ scanf("%d%d", &n, &t); for (int i = 1; i < n; i++) { int u, v; scanf("%d%d", &u, &v); G[u].push_back(v); G[v].push_back(u); } dfs(n, 0); int u = 1; while (t--&&u != n) { u = fa[u]; } dfs2(u, 0); for (int i = 1; i <= n; i++)vc[d2[i]].push_back(i); int ans = 0; for (int i = 0; i < n; i++) { bool flg = 0; for (int u : vc[i]) { ans = max(ans, (d1[u] + 1) / 2); if ((d1[u] + 1) / 2 > i) { flg = 1; } } if (!flg)break; } printf("%d\n", ans); return0; }
做法二:bfs
第一种做法只在速度为1,2时可行,并不推荐。
要找到一条从 u 出发,并且每一步都不会被追到的最长路径(每一步距离 n 比 距离 u 更远),用bfs找合法路径是很基本的了。