P5384 [Cnoi2019] 雪松果树

cxqghzj·2023-09-22 09:24·14 次阅读

P5384 [Cnoi2019] 雪松果树

题意#

给定一棵 N 个节点的树。

每次询问求 u 节点的 k-cousin 有多少个。

Sol#

将该问题拆分为两个问题。

  • u 节点的 k-father。
  • u 节点的 k-son 的个数。

第一个子问题很好做,在 dfs 时记录一下最后一次访问的该深度的节点即可。

对于第二个,我们考虑对于每个深度建一个 vector 然后将 dfs 序扔进去。

查询 u 节点的 k-son 数就变成了在 dep[u+k] 上二分查找左端点 >dfn[u] 右端点 <dfn[u]+siz[u]1 即可。

注意判断非法情况。

Code#

Copy
#include <iostream> #include <algorithm> #include <cstdio> #include <array> #include <vector> #define pii pair <int, int> using namespace std; #ifdef ONLINE_JUDGE #define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++) char buf[1 << 23], *p1 = buf, *p2 = buf, ubuf[1 << 23], *u = ubuf; #endif int read() { int p = 0, flg = 1; char c = getchar(); while (c < '0' || c > '9') { if (c == '-') flg = -1; c = getchar(); } while (c >= '0' && c <= '9') { p = p * 10 + c - '0'; c = getchar(); } return p * flg; } void write(int x) { if (x < 0) { x = -x; putchar('-'); } if (x > 9) { write(x / 10); } putchar(x % 10 + '0'); } #define fi first #define se second const int N = 1e6 + 5; namespace G { array <int, N> fir, nex, to; int cnt; void add(int x, int y) { cnt++; nex[cnt] = fir[x]; to[cnt] = y; fir[x] = cnt; } } array <pii, N> qs; namespace Hpt { using G::fir, G::nex, G::to; array <int, N> siz, dep, dfn; array <int, N> prl; array <vector <int>, N> isl, cur; int cnt; void dfs(int x) { cnt++; prl[dep[x]] = x; for (auto y : cur[x]) { if (dep[x] < qs[y].se) { qs[y].fi = -1; continue; } qs[y].fi = prl[dep[x] - qs[y].se]; } siz[x] = 1; dfn[x] = cnt; isl[dep[x]].push_back(cnt); for (int i = fir[x]; i; i = nex[i]) { dep[to[i]] = dep[x] + 1; dfs(to[i]); siz[x] += siz[to[i]]; } } } int main() { int n = read(), q = read(); for (int i = 2; i <= n; i++) { int x = read(); G::add(x, i); } for (int i = 1; i <= q; i++) { qs[i].fi = read(), qs[i].se = read(); Hpt::cur[qs[i].fi].push_back(i); } Hpt::dfs(1); using Hpt::dep, Hpt::isl, Hpt::siz, Hpt::dfn; for (int i = 1; i <= q; i++) { if (!(~qs[i].fi)) { printf("0 "); continue; } int pos = dep[qs[i].fi] + qs[i].se; int ans = upper_bound(isl[pos].begin(), isl[pos].end(), dfn[qs[i].fi] + siz[qs[i].fi] - 1) - lower_bound(isl[pos].begin(), isl[pos].end(), dfn[qs[i].fi]) - 1; /* for (auto x : isl[pos]) { */ /* write(x), putchar(32); */ /* } */ /* puts(""); */ write(ans), putchar(32); } puts(""); return 0; }
posted @   cxqghzj  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示
目录