您的位置:首页 > 其它

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

2013-04-01 14:33 323 查看
题目链接: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|1

const int N = 1e5+3;

vector<int> g
;

struct Int
{
    int a,b;
}I
;

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: