ZOJ3696-A Simple Tree Problem 线段树

来源:互联网 发布:淘宝开店人脸认证失败 编辑:程序博客网 时间:2024/06/05 15:56

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 21 1o 2q 1

Sample Output

1
水题,先dfs,再线段树

/*  * File:   main.cpp * Author: Kevin * * Created on 2013年10月28日, 下午3:56 */#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<string>#include<vector>#include<utility>using namespace std;#define MAXN 100005#define lson(x) (x<<1)#define rson(x) (x<<1|1)#define pret(x) (x>>1)#define lens(x) (cord[x].second-cord[x].first+1)typedef pair<int, int> pr;vector<int>vt[MAXN];pr mk[MAXN];/**************线段树相关数组***************/pr cord[MAXN<<2]; //区间端点int sum[MAXN<<2]; //所求答案int flag[MAXN<<2]; //延迟标记/********线段树的最大值应该是点数4倍**********/int id;void dfs(int rt) {    mk[rt].first = ++id;    for (int i = 0; i < vt[rt].size(); i++) {        int v = vt[rt][i];        if (mk[v].first == 0)dfs(v);    }    mk[rt].second = id;}void pushup(int rt) {    sum[rt] = sum[lson(rt)] + sum[rson(rt)];}void pushdown(int rt) {    if (flag[rt]) {        flag[rt] = 0;        flag[lson(rt)] ^= 1;        flag[rson(rt)] ^= 1;        sum[lson(rt)] = lens(lson(rt)) - sum[lson(rt)];        sum[rson(rt)] = lens(rson(rt)) - sum[rson(rt)];    }}void build(int l, int r, int rt) {    cord[rt] = make_pair(l, r);    flag[rt] = sum[rt] = 0;    if (l == r)return;    int m = pret(l + r);    build(l, m, lson(rt));    build(m + 1, r, rson(rt));}void update(int l, int r, int rt) {    if (cord[rt].first >= l && cord[rt].second <= r) {        flag[rt] ^= 1;        sum[rt] = lens(rt) - sum[rt];        return;    }    pushdown(rt);    int m = pret(cord[rt].first + cord[rt].second);    if (l <= m)update(l, r, lson(rt));    if (r >= m + 1)update(l, r, rson(rt));    pushup(rt);}int query(int l, int r, int rt) {    if (cord[rt].first >= l && cord[rt].second <= r) {        return sum[rt];    }    int ret = 0;    int m = pret(cord[rt].first + cord[rt].second);    pushdown(rt);    if (l <= m)ret += query(l, r, lson(rt));    if (r >= m + 1)ret += query(l, r, rson(rt));    return ret;}int main(int argc, char** argv) {    int n, m;    while (~scanf("%d%d", &n, &m)) {        for (int i = 1; i <= n; i++)vt[i].clear();        for (int i = 2; i <= n; i++) {            int x;            scanf("%d", &x);            vt[x].push_back(i);        }        for (int i = 1; i <= n; i++)mk[i].first = 0;        id = 0;        dfs(1);        build(1, n, 1);        while (m--) {            char c; int x;            scanf("%*c%c%d", &c, &x);            if (c == 'o')                 update(mk[x].first, mk[x].second, 1);            else                 printf("%d\n", query(mk[x].first, mk[x].second, 1));        }        printf("\n");    }    return 0;}