DFS序 (非递归)
Posted zeronera
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DFS序 (非递归)相关的知识,希望对你有一定的参考价值。
递归爆栈了,改了半天非递归的,记录一下
求以某个结点为根的子树中权值大于k的结点的数量
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1000010;
typedef long long ll;
int in[maxn], out[maxn], tim,p;
struct ss
{
int id, st;
ss(int _id = 0, int _st = 0) : id(_id), st(_st) {}
} sta[maxn];
struct node
{
int v, next;
} edge[maxn << 1];
int head[maxn], cnt;
void add(int x, int y) //无向边开边数两倍大小 切记
{
edge[++cnt].v = y;
edge[cnt].next = head[x];
head[x] = cnt;
}
void dfs(int u)
{
in[u] = ++tim;
sta[p++] = ss(u,head[u]);
while (p)
{
ss now = sta[p - 1];
for (int i = now.st; i != 0;)
{
int nx = edge[i].v;
if (!in[nx])
{
sta[p-1]=ss(now.id,edge[i].next);
in[nx] = ++tim;
sta[p++] = ss(nx,head[nx]);
i = head[nx];
now = sta[p - 1];
}
else
i = edge[i].next;
}
out[sta[p - 1].id] = tim;
p--;
}
}
int T[maxn], L[maxn * 30], R[maxn * 30], sum[maxn * 30];
int sz[maxn], h[maxn];
int n, q, k, tot;
void build(int &rt, int l, int r)
{
rt = ++tot;
sum[rt] = 0;
if (l == r)
return;
int mid = (l + r) >> 1;
build(L[rt], l, mid);
build(R[rt], mid + 1, r);
}
void update(int &rt, int l, int r, int pre, int x)
{
rt = ++tot;
L[rt] = L[pre];
R[rt] = R[pre];
sum[rt] = sum[pre] + 1;
if (l == r)
return;
int mid = (l + r) >> 1;
if (x <= mid)
update(L[rt], l, mid, L[pre], x);
else
update(R[rt], mid + 1, r, R[pre], x);
}
int query(int s, int e, int l, int r, int k) //区间小于等于k的数的个数
{
if (l == r)
return sum[e] - sum[s];
int mid = (l + r) >> 1;
if (k <= mid)
return query(L[s], L[e], l, mid, k);
else
return sum[L[e]] - sum[L[s]] + query(R[s], R[e], mid + 1, r, k);
}
inline int read()
{
int sgn = 1;
int cnt = 0;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-')
sgn = -sgn;
ch = getchar();
}
while ('0' <= ch && ch <= '9')
{
cnt = cnt * 10 + (ch - '0');
ch = getchar();
}
return sgn * cnt;
}
int main()
{
int n, u, v, x;
n = read();
for (int i = 1; i <= n; i++)
{
h[i] = read();
h[i]++;
}
for (int i = 1; i <= n - 1; i++)
{
u = read();
v = read();
add(u, v);
add(v, u);
}
dfs(1);
for (int i = 1; i <= n; i++)
sz[in[i]] = h[i];
tot = 0;
build(T[0], 1, maxn);
for (int i = 1; i <= n; i++)
update(T[i], 1, maxn, T[i - 1], sz[i]);
q = read();
while (q--)
{
x = read();
k = read();
k++;
printf("%d
", query(T[in[x] - 1], T[out[x]], 1, maxn, k));
}
return 0;
}
以上是关于DFS序 (非递归)的主要内容,如果未能解决你的问题,请参考以下文章