ZOJ 3686 A Simple Tree Problem(将对树的操作转化成区间=>线段树)

来源:互联网 发布:淘宝电商学院哪个好 编辑:程序博客网 时间:2024/06/05 15:16

题目链接:Click here~~

题意:

给一颗确定的树,每个节点只有 0 和 1 两种状态。

两种操作:1、将某颗子树的0变1,1变0。

                  2、询问某颗子树的1的个数。

解题思路:

一看这两种操作,很容易就联想到了线段树,但问题是,区间在哪里???

由于操作都是对一颗树进行的,我们要想办法把它和区间联系起来。

不妨把 每个节点都看做一个数,每棵树都看做一个区间。

因为一共有 n 个点,我们把树根看做1,区间看做 [1,n]。

树根的孩子看做多少呢?2、3、4、5、6?

显然是不可以的,因为这样对 “2” 这颗树操作的时候,"2" 的子树不再是一段区间。

所以,3 应该让 "2" 的孩子来当。

…… 依次类推,怎么样,很像递归吧?

如果没懂的话,画个图仔细想想吧。

做法嘛,dfs 一下就好了。

转化成区间之后,就是很简单的 线段树 问题了。

#include <vector>#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;#define lson u<<1#define rson u<<1|1const int N = 1e5+3;vector<int> g[N];struct Int{    int a,b;}I[N];int id;void dfs(int u){    I[u].a = ++id;    for(int i=0;i<(int)g[u].size();i++)        dfs(g[u][i]);    I[u].b = id;}struct SegTree{    int l,r,sum,lazy;    inline int mid()    {        return l+r >> 1;    }    inline int len()    {        return r-l;    }}T[N<<2];void push_down(int u){    if(!T[u].lazy)        return ;    T[lson].sum = T[lson].len() - T[lson].sum;    T[rson].sum = T[rson].len() - T[rson].sum;    T[lson].lazy ^= 1;    T[rson].lazy ^= 1;    T[u].lazy = 0;}void push_up(int u){    T[u].sum = T[lson].sum + T[rson].sum;}void build(int u,int l,int r){    T[u].l = l , T[u].r = r;    T[u].sum = T[u].lazy = 0;    if(l == r-1)    {        return ;    }    int m = T[u].mid();    build(lson,l,m);    build(rson,m,r);}void updata(int u,int l,int r){    if(l == T[u].l && r == T[u].r)    {        T[u].sum = T[u].len() - T[u].sum;        T[u].lazy ^= 1;        return ;    }    push_down(u);    int m = T[u].mid();    if(r <= m)        updata(lson,l,r);    else if(l >= m)        updata(rson,l,r);    else    {        updata(lson,l,m);        updata(rson,m,r);    }    push_up(u);}int query(int u,int l,int r){    if(l == T[u].l && r == T[u].r)        return T[u].sum;    push_down(u);    int m = T[u].mid();    if(r <= m)        return query(lson,l,r);    else if(l >= m)        return query(rson,l,r);    else        return query(lson,l,m) + query(rson,m,r);}int main(){    int n,Q,u;    char cmd[5];    while(~scanf("%d%d",&n,&Q))    {        for(int i=1;i<=n;i++)            g[i].clear();        for(int i=2;i<=n;i++)        {            int num;            scanf("%d",&num);            g[num].push_back(i);        }        id = 0;        dfs(1);        build(1,1,n+1);        while(Q--)        {            scanf("%s%d",cmd,&u);            if(cmd[0] == 'o')                updata(1,I[u].a,I[u].b+1);            else                printf("%d\n",query(1,I[u].a,I[u].b+1));        }        puts("");    }    return 0;}


原创粉丝点击