• 2014 Super Training #9 F A Simple Tree Problem --DFS+线段树


    原题: ZOJ 3686 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3686

    这题本来是一个比较水的线段树,结果一个mark坑了我好几个小时。。哎。太弱。

    先DFS这棵树,树形结构转换为线性结构,每个节点有一个第一次遍历的时间和最后一次遍历的时间,之间的时间戳都为子树的时间戳,用线段树更新这段区间即可实现更新子树的效果,用到懒操作节省时间。

    坑我的地方: update时,不能写成:tree[rt].mark = 1, 而要写成 tree[rt].mark ^= 1; 因为如果持续update偶数次相当于什么都没做,但是每次update确实是更新了的啊,每次pushdown都会将tree[rt].mark变为0的啊,也就是说tree[rt].mark是不能保持的,所以我搞不懂的是为什么要异或1,而不能直接令等于1,有待向大神请教,如果有看到并知道的仁兄可以指教一下我。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    using namespace std;
    #define N 100007
    
    struct node
    {
        int l,r;
    }p[N];
    
    struct Tree
    {
        int sum,mark;
    }tree[8*N];
    int Time;
    vector<int> G[N];
    
    void pushup(int rt)
    {
        tree[rt].sum = tree[2*rt].sum + tree[2*rt+1].sum;
    }
    
    void build(int l,int r,int rt)
    {
        tree[rt].sum = tree[rt].mark = 0;
        if(l == r)
            return;
        int mid = (l+r)/2;
        build(l,mid,2*rt);
        build(mid+1,r,2*rt+1);
        pushup(rt);
    }
    
    void pushdown(int l,int r,int rt)
    {
        if(!tree[rt].mark)
            return;
        int mid = (l+r)/2;
        tree[2*rt].mark ^= 1;           //not "tree[2*rt].mark = tree[rt].mark"
        tree[2*rt+1].mark ^= 1;
        tree[2*rt].sum = (mid-l+1)-tree[2*rt].sum;
        tree[2*rt+1].sum = (r-mid)-tree[2*rt+1].sum;
        tree[rt].mark = 0;
    }
    
    void update(int l,int r,int aa,int bb,int rt)
    {
        if(aa<=l && bb>=r)
        {
            tree[rt].mark ^= 1;   //not "tree[rt].mark = 1", 因为偶数次操作相互抵消
            tree[rt].sum = r-l+1-tree[rt].sum;
            return;
        }
        pushdown(l,r,rt);
        int mid = (l+r)/2;
        if(aa <= mid)
            update(l,mid,aa,bb,2*rt);
        if(bb > mid)
            update(mid+1,r,aa,bb,2*rt+1);
        pushup(rt);
    }
    
    void dfs(int u)
    {
        p[u].l = Time++;
        for(int i=0;i<G[u].size();i++)
            dfs(G[u][i]);
        p[u].r = Time++;
    }
    
    int query(int l,int r,int aa,int bb,int rt)
    {
        if(aa>r || bb<l)
            return 0;
        if(aa<=l && bb>=r)
            return tree[rt].sum;
        pushdown(l,r,rt);
        int mid = (l+r)/2;
        return query(l,mid,aa,bb,2*rt)+query(mid+1,r,aa,bb,2*rt+1);
    }
    
    int main()
    {
        int n,m,i,j,x;
        char ss[3];
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            for(i=0;i<=n;i++)
                G[i].clear();
            for(i=2;i<=n;i++)
            {
                scanf("%d",&x);
                G[x].push_back(i);
            }
            Time = 1;
            dfs(1);
            build(1,2*n,1);
            while(m--)
            {
                scanf("%s%d",ss,&x);
                if(ss[0] == 'o')
                    update(1,2*n,p[x].l,p[x].r,1);
                else
                    printf("%d
    ",query(1,2*n,p[x].l,p[x].r,1)/2);
            }
            puts("");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    SHL逻辑测试题饼状图
    SHL逻辑测试柱状图
    SHL逻辑测试折线图
    【C++ 继承】调用基类的虚函数
    【C++ 11 | thread】交替输出“ABC”

    【cmake】命令set
    【Linux】读写锁
    【cmake】project
    【Linux系统编程】互斥锁和自旋锁
  • 原文地址:https://www.cnblogs.com/whatbeg/p/3830447.html
Copyright © 2020-2023  润新知