zoukankan      html  css  js  c++  java
  • BNU 28887——A Simple Tree Problem——————【将多子树转化成线段树+区间更新】

    A Simple Tree Problem

    Time Limit: 3000ms
    Memory Limit: 65536KB
    This problem will be judged on ZJU. Original ID: 3686
    64-bit integer IO format: %lld      Java class name: Main
    Type: 
    None
     
     

    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
    

    题目大意:有棵根节点为1的树,共有n个节点。有m次询问。第二行为从2--->n各个节点对应的父亲节点编号。下面的m行是询问,o  ai表示将节点为ai的子树所有节点的值进行异或即0变1,1变0。q ai表示询问目前该子树的节点的和值为多少。

    解题思路:其实这个题目重点在如何将多子树转化成线段树进行操作。我们如果重新将树编号,那么可以让每个节点对应一段区间。从根节点1开始深搜,编号为1,每当搜到一个节点,就让编号的值加1,让这个编号等于该节点的区间左端点,等把该节点的所有子节点访问完后,将这时的编号赋值给该节点的区间右端点。这时这个区间内的所有节点都是该节点的子节点。  后边就是区间更新的问题了。

    #include<bits/stdc++.h>
    using namespace std;
    #define mid (L+R)/2
    #define lson rt*2,L,mid
    #define rson rt*2+1,mid+1,R
    const int maxn=1e5+50;
    vector<int>G[maxn];
    int Lt[maxn],Rt[maxn];
    int sumv[maxn*4],lazy[maxn*4];
    int n,cn;
    void dfs(int u){
        Lt[u]=++cn;
        int v;
        for(int i=0;i<G[u].size();i++){
            v=G[u][i];
            dfs(v);
        }
        Rt[u]=cn;
    }
    void build(int rt,int L,int R){
        sumv[rt]=lazy[rt]=0;
        if(L==R)
            return ;
        build(lson);
        build(rson);
    }
    void PushDown(int rt,int L,int R){
        if(lazy[rt]){
            lazy[rt*2]^=1;
            lazy[rt*2+1]^=1;
            sumv[rt*2]=(mid-L+1)-sumv[rt*2];    
            sumv[rt*2+1]=(R-mid)-sumv[rt*2+1];  
            lazy[rt]=0;
        }
    }
    void PushUp(int rt){
        sumv[rt]=sumv[rt*2]+sumv[rt*2+1];
    }
    void update(int rt,int L,int R,int l_ran,int r_ran){
        if(l_ran<=L&&R<=r_ran){
            lazy[rt]^=1;
            sumv[rt]=R-L+1-sumv[rt];
            return ;
        }
        PushDown(rt,L,R);
        if(l_ran<=mid){
            update(lson,l_ran,r_ran);
        }
        if(r_ran>mid){
            update(rson,l_ran,r_ran);
        }
        PushUp(rt);
    }
    int query(int rt,int L,int R,int l_ran,int r_ran){
        if(l_ran<=L&&R<=r_ran){
            return sumv[rt];
        }
        int ret=0;
        PushDown(rt,L,R); //lazy下放
        if(l_ran<=mid){
            ret+=query(lson,l_ran,r_ran);
        }
        if(r_ran>mid){
            ret+=query(rson,l_ran,r_ran);
        }
        return ret;
    }
    int main(){
        char s[4];
        int m,subt,a,res;
        while(scanf("%d%d",&n,&m)!=EOF){
            build(1,1,n);
            for(int i=0;i<=n;i++)
                G[i].clear();
            for(int i=2;i<=n;i++){
                scanf("%d",&a);
                G[a].push_back(i);
            }
            cn=0;
            dfs(1);
            for(int i=0;i<m;i++){
                scanf("%s%d",s,&subt);
                if(s[0]=='o'){
                    update(1,1,n,Lt[subt],Rt[subt]);
                }else{
                    res=query(1,1,n,Lt[subt],Rt[subt]);
                    printf("%d
    ",res);
                }
            }printf("
    ");
    
        }
        return 0;
    }
    
    
    /*
    6 5
    1 2 1 4 4
    o 4
    q 4
    q 5
    q 6
    q 1
    */
    

      

  • 相关阅读:
    Ubuntu中安装mysql(一)
    磁盘格式化分区挂载
    mysql主从&主主部署记录
    python基础-编码环境安装与基本语法
    测试报告应包含的内容信息
    HTTP协议数据包简单总结
    支付功能测试点
    Android--monkey测试命令
    Fiddler 抓包学习_下载安装配置
    chrome F12_Network 开发者工具详解
  • 原文地址:https://www.cnblogs.com/chengsheng/p/4682131.html
Copyright © 2011-2022 走看看