P8844 题解
xiaoyang222 · · 题解
前言
这里给两个完全不需要高级数据结构的做法。一个
题解
第一种做法
来自班上同学。
由于是染
但是这样每个点是
容易发现一点是:把树看成一层一层的,然后发现一个点的子树内同一高度的点都在类似一段里。然后可以通过对深搜序二分出左端点和右端点。显然可以做前缀和。
在线算法,时间复杂度
代码放一个他的暴力。
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int N = 1e5 + 10;
int n, m, Dep;
int Size[N];
vector<int> g[N], td[N];
int ins[N], tot;
int dep[N];
void DFS(int now, int fa) {
dep[now] = dep[fa] + 1;
td[dep[now]].push_back(now);
Size[now] = 1;
ins[now] = ++tot;
for (int to : g[now])
if (to != fa)
DFS(to, now), Size[now] += Size[to];
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n >> m;
for (int i = 1; i < n; ++i) {
int x, y;
cin >> x >> y;
g[x].push_back(y);
g[y].push_back(x);
}
DFS(1, 0);
for (int i = 1; i <= m; ++i) {
int op, x;
cin >> op >> x;
if (op == 1)
Dep = x;
else {
if (Dep == 0) {
cout << 0 << "\n";
continue;
}
if (Dep <= dep[x])
cout << Size[x] << "\n";
else {
int ans = 0;
for (int j : td[Dep])
if (ins[j] < ins[x] + Size[x] && ins[x] <= ins[j])
ans += Size[j];
cout << ans << "\n";
}
}
}
return 0;
}
第二种做法
来自我。完全不用数据结构。
铺垫是借鉴第一种做法的开初思路,即“只统计
把询问挂到树上,记录询问编号和
可以想一下从根开始 dfs,当到这个点的询问,就记一下当前要求的
对于“这个值”,是之前遍历过的所有点中深度为当前下标的子树大小和。具体见下面代码。
离线算法,
#include <iostream>
#include <vector>
using namespace std;
const int N = 1e5 + 5;
vector<int> g[N];
vector<pair<int, int>> query[N];
int a1[N], b1[N];
int ans1[N], ans2[N], d[N], siz[N], sm[N], n, m;
void init(int u, int fa) {
d[u] = d[fa] + 1;
++siz[u];
for (int &v : g[u]) {
if (v == fa)
continue;
init(v, u);
siz[u] += siz[v];
}
}
void dfs(int u, int fa) {
for (auto &q : query[u]) {
ans1[q.second] = sm[q.first];
}
sm[d[u]] += siz[u];
for (int &v : g[u]) {
if (v == fa)
continue;
dfs(v, u);
}
for (auto &q : query[u]) {
if (d[u] >= q.first)
ans2[q.second] = ans1[q.second] + siz[u];
else
ans2[q.second] = sm[q.first];
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n >> m;
for (int i = 1, u, v; i < n; ++i) {
cin >> u >> v;
g[u].emplace_back(v), g[v].emplace_back(u);
}
int w = n + 1, tot = 0;
for (int i = 1, op, x; i <= m; ++i) {
cin >> op >> x;
if (op == 1)
w = x;
else
a1[tot] = x, b1[tot] = w, query[x].emplace_back(w, ++tot);
}
init(1, 0);
dfs(1, 0);
for (int i = 1; i <= tot; ++i) {
cout << ans2[i] - ans1[i] << "\n";
}
cout.flush();
return 0;
}