• 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;
    }
    
  • 相关阅读:
    C#基础篇十小练习
    C#基础篇九OOP属性结构枚举
    C#基础篇八构造函数和面向对象思想
    C#基础篇七类和静态成员
    C#基础篇六飞行棋
    C#基础篇五值类型和引用类型
    数据与地址的自动给定---基于状态机
    SPI 核的寄存器空间
    mig_7series DDR控制器的配置
    关于zynq7 中MIO的理解
  • 原文地址:https://www.cnblogs.com/Zeronera/p/11779137.html
Copyright © 2020-2023  润新知