CF1320E Treeland and Viruses
Treeland and Viruses
题面翻译
有一棵有
Solution
标的 *3000,体感 *2300,因为我会做😎(虽然套路)。
考虑暴力怎么做。不难想到一种每次询问都是
注意到题目保证了询问的
代码实现有一些细节需要注意,总时间复杂度
Code
int N, Q, K, M;
namespace RealTree {
vector<int> e[_N];
int siz[_N], son[_N], dep[_N], fa[_N], top[_N], dfn[_N], tot;
void addEdge(int x, int y) {e[x].epb(y), e[y].epb(x);}
void dfs1(int x, int F) {
fa[x] = F, dep[x] = dep[F] + 1, siz[x] = 1;
for (int v: e[x]) if (v ^ F) {
dfs1(v, x), siz[x] += siz[v];
if (siz[v] > siz[son[x]]) son[x] = v;
}
}
void dfs2(int x, int topf) {
top[x] = topf, dfn[x] = ++tot;
if (son[x]) dfs2(son[x], topf);
for (int v: e[x]) if (v ^ son[x] && v ^ fa[x])
dfs2(v, v);
}
inline void init() {dfs1(1, 0), dfs2(1, 1);}
int getLca(int x, int y) {
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
x = fa[top[x]];
}
return dep[x] < dep[y] ? x : y;
}
int getDis(int x, int y) {return dep[x] + dep[y] - 2 * dep[getLca(x, y)];}
}
namespace VirtTree {
vector<int> e[_N];
vector<int> pset;
void addEdge(int x, int y) {e[x].epb(y), e[y].epb(x);}
void build(vector<int> p) {
auto cmp = [&](const auto &i, const auto &j) {
return RealTree::dfn[i] < RealTree::dfn[j];
};
sort(All(p), cmp);
vector<int> vec = p;
For(i, 1, p.size() - 1)
vec.epb(RealTree::getLca(p[i], p[i-1]));
sort(All(vec), cmp);
vec.resize(unique(All(vec)) - vec.begin());
for (int x: vec) e[x].clear();
For(i, 1, vec.size() - 1) {
int lca = RealTree::getLca(vec[i-1], vec[i]);
addEdge(lca, vec[i]);
}
pset.swap(vec);
}
}
vector<pii> crl;
vector<int> qlist;
int ans[_N], id[_N];
pii dist[_N];
bool vis[_N];
void init() {
for (int x: VirtTree::pset) id[x] = 0;
For(i, 0, M - 1) id[qlist[i]] = i + 1;
for (int x: VirtTree::pset) {
dist[x] = mkp(inf, inf);
vis[x] = 0;
}
}
void Solve() {
using VirtTree::e, RealTree::getDis;
init();
priority_queue<pair<pii, int>> q;
For(i, 0, K - 1) {
auto [x, s] = crl[i];
q.emplace(mkp(0, -i - 1), x);
dist[x] = mkp(0, i + 1), ans[id[x]] = i + 1;
}
while (!q.empty()) {
auto cur = q.top(); q.pop();
if (vis[cur.se]) continue;
vis[cur.se] = 1;
for (int v: e[cur.se]) {
int d = getDis(crl[-cur.fi.se-1].fi, v);
int t = ceil(d * 1. / crl[-cur.fi.se-1].se);
if (dist[v] > mkp(t, -cur.fi.se)) {
dist[v] = mkp(t, -cur.fi.se);
ans[id[v]] = -cur.fi.se;
q.emplace(mkp(-t, cur.fi.se), v);
}
}
}
}
void _() {
cin >> N;
For(i, 2, N) {
int x, y; cin >> x >> y;
RealTree::addEdge(x, y);
}
RealTree::init();
cin >> Q;
while (Q--) {
cin >> K >> M;
crl.resize(K), qlist.resize(M);
vector<int> p;
for (auto &pr: crl) cin >> pr.fi >> pr.se, p.epb(pr.fi);
for (int &x: qlist) cin >> x, p.epb(x);
VirtTree::build(p);
Solve();
For(i, 1, M) fmtout("{} ", ans[i]);
fmtout("\n");
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步