• dfs序题集


    dfs序可以维护一个子树内的信息

    需要记录dfs进的时间以及所有子树都遍历完的时间

    void dfs(int u, int fa)
    {
        L[u] = ++id;
        for(int i = head[u]; ~i; i = e[i].next)
        {
            int v = e[i].to;
            if(v == fa) continue;
            dfs(v, u);
        }
        R[u] = id;
    }

    那么对于点i,L[i]到R[i]就是i的子树(包括i)

    那么子树内维护信息就可以用树状数组,线段树之内的乱搞了。

    poj 3321

    用树状数组维护就好。

    注意修改的时候一定是修改序列

    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #define REP(i, a, b) for(register int i = (a); i < (b); i++)
    #define _for(i, a, b) for(register int i = (a); i <= (b); i++)
    using namespace std;
     
    const int MAXN = 1e5 + 10;
    struct Edge{ int to, next; };
    Edge e[MAXN << 1];
    int head[MAXN], num, n, m;
    int L[MAXN], R[MAXN], s[MAXN], id;
    
    struct Binary_Index_Tree
    {
        int f[MAXN];
        
        Binary_Index_Tree() { memset(f, 0, sizeof(f)); }
        
        int lowbit(int x) { return x & (-x); }
        
        void add(int x, int p)
        {
            while(x <= n)
            {
                f[x] += p; 
                x += lowbit(x);
            }
        }
        
        int sum(int x)
        {
            int res = 0;
            while(x)
            {
                res += f[x];
                x -= lowbit(x);
            }
            return res;
        }
        
        int query(int l, int r) { return sum(r) - sum(l - 1); }
    }S;
     
    void read(int& x)
    {
        int f = 1; x = 0; char ch = getchar();
        while(!isdigit(ch)) { if(ch == '-') f = -1; ch = getchar(); }
        while(isdigit(ch)) { x = x * 10 + ch - '0'; ch = getchar(); }
        x *= f;
    }
     
    void AddEdge(int to, int from)
    {
        e[num] = Edge{to, head[from]};
        head[from] = num++;
    }
     
    void dfs(int u, int fa)
    {
        L[u] = ++id;
        for(int i = head[u]; ~i; i = e[i].next)
        {
            int v = e[i].to;
            if(v == fa) continue;
            dfs(v, u);
        }
        R[u] = id;
    }
     
    int main()
    {
        memset(head, -1, sizeof(head)); num = 0;
        read(n);
        REP(i, 1, n)
        {
            int u, v; read(u), read(v);
            AddEdge(u, v); AddEdge(v, u); 
        }
        _for(i, 1, n) 
        {
            s[i] = 1;
            S.add(i, 1);
        }
        
        dfs(1, -1);
        read(m);
        
        while(m--)
        {
            char op[5]; int x;
            scanf("%s", op); read(x);
            if(op[0] == 'Q') printf("%d
    ", S.query(L[x], R[x]));
            else
            {
                int id = L[x];
                if(s[id]) S.add(id, -1);
                else S.add(id, 1);
                s[id] = !s[id];
            }
        }
    
        return 0;
    }
  • 相关阅读:
    Shell 函数
    Shell test命令/流程控制
    Shell 变量/echo命令
    Linux vi/vim and linux yum 命令
    Linux磁盘管理
    Linux 用户和用户组管理
    Linux 文件与目录管理
    Linux root用户密码重置,远程登陆,文件基本属性
    Linux简介安装、系统启动过程、目录结构
    Linux系统安装时分区的介绍
  • 原文地址:https://www.cnblogs.com/sugewud/p/9819296.html
Copyright © 2020-2023  润新知