zoukankan      html  css  js  c++  java
  • ZOJ 3686 A Simple Tree Problem(线段树)

    A Simple Tree Problem

    Time Limit: 3 Seconds      Memory Limit: 65536 KB

    Given a rooted tree, each node has a boolean (0 or 1) labeled on it. Initially, all the labels are 0.

    We define this kind of operation: given a subtree, negate all its labels.

    And we want to query the numbers of 1's of a subtree.

    Input

    Multiple test cases.

    First line, two integer N and M, denoting the numbers of nodes and numbers of operations and queries.(1<=N<=100000, 1<=M<=10000)

    Then a line with N-1 integers, denoting the parent of node 2..N. Root is node 1.

    Then M lines, each line are in the format "o node" or "q node", denoting we want to operate or query on the subtree with root of a certain node.

    Output

    For each query, output an integer in a line.

    Output a blank line after each test case.

    Sample Input

    3 2
    1 1
    o 2
    q 1
    

    Sample Output

    1
    

    题意:给你一颗树。而且有两种操作,一种是将以节点i为root的子树每一个节点上的值取反,另一种操作时
           查询以节点i为root的子树全部节点上的值得和。节点上的值不是1就是0,初始皆为0。

    题解:把子树化为区间的就是裸的线段树了。我们能够先序遍历树,把以x为根节点的子树的用L[x],R[x]区间表示
             然后就是线段树区间更新了。

    #include<cstring>
    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<vector>
    #include<algorithm>
    #define lc idx<<1
    #define rc idx<<1|1
    #define lson l,mid,lc
    #define rson mid+1,r,rc
    #define N 100010
    
    using namespace std;
    
    int n,m;
    vector<int>G[N];
    int L[N],R[N],id;
    
    struct Tree {
        int st;
        int one;
    } tree[N<<2];
    
    void init() {
        for(int i=0; i<=n; i++)
            G[i].clear();
        id=1;
    }
    
    void dfs(int fa) {
        L[fa]=id++;
        for(int i=0; i<G[fa].size(); i++) {
            dfs(G[fa][i]);
        }
        R[fa]=id-1;
    }
    
    void push_up(int idx) {
        tree[idx].one=tree[lc].one+tree[rc].one;
    }
    
    void push_down(int idx,int m) {
        if(tree[idx].st) {
            tree[lc].st^=1,tree[rc].st^=1;
            tree[idx].st=0;
            tree[lc].one=m-m/2-tree[lc].one;
            tree[rc].one=m/2-tree[rc].one;
        }
    }
    
    void build(int l,int r,int idx) {
        tree[idx].one=0;
        tree[idx].st=0;
        if(l==r)return;
        int mid=(l+r)>>1;
        build(lson);
        build(rson);
    }
    
    void update(int l,int r,int idx,int x,int y) {
        if(x<=l&&r<=y) {
            tree[idx].st^=1;
            tree[idx].one=r-l+1-tree[idx].one;
            return;
        }
        push_down(idx,r-l+1);
        int mid=(l+r)>>1;
        if(x<=mid)update(lson,x,y);
        if(y>mid) update(rson,x,y);
        push_up(idx);
    }
    
    int query(int l,int r,int idx,int x,int y) {
        if(x<=l&&r<=y)
            return tree[idx].one;
        push_down(idx,r-l+1);
        int mid=(l+r)>>1;
        int ans=0;
        if(x<=mid) ans+=query(lson,x,y);
        if(y>mid)  ans+=query(rson,x,y);
        return ans;
    }
    
    int main() {
        //freopen("test.in","r",stdin);
        while(~scanf("%d%d",&n,&m)) {
            init();
            int fa;
            for(int i=2; i<=n; i++) {
                scanf("%d",&fa);
                G[fa].push_back(i);
            }
            dfs(1);
            build(1,n,1);
            char c[3];
            int rt;
            while(m--) {
                scanf("%s%d",c,&rt);
                if(c[0]=='o') {
                    update(1,n,1,L[rt],R[rt]);
                    continue;
                }
                printf("%d
    ",query(1,n,1,L[rt],R[rt]));
            }
            printf("
    ");
        }
        return 0;
    }


  • 相关阅读:
    SQL的增删改查
    SQL语句的分类
    创建新DB和新用户&DBeaver连接
    jQuery css() 方法:设置或返回被选元素的一个或多个样式属性
    jQuery
    jQuery
    jQuery
    jQuery
    jQuery
    jQuery
  • 原文地址:https://www.cnblogs.com/tlnshuju/p/7000394.html
Copyright © 2011-2022 走看看