Codeforces 877E Danil and a Part-time Job(DFS序构造线段树+区间维护)*

Danil decided to earn some money, so he had found a part-time job. The interview have went well, so now he is a light switcher.

Danil works in a rooted tree (undirected connected acyclic graph) with n vertices, vertex 1 is the root of the tree. There is a room in each vertex, light can be switched on or off in each room. Danil's duties include switching light in all rooms of the subtree of the vertex. It means that if light is switched on in some room of the subtree, he should switch it off. Otherwise, he should switch it on.

Unfortunately (or fortunately), Danil is very lazy. He knows that his boss is not going to personally check the work. Instead, he will send Danil tasks using Workforces personal messages.

There are two types of tasks:

  1. pow v describes a task to switch lights in the subtree of vertex v.
  2. get v describes a task to count the number of rooms in the subtree of v, in which the light is turned on. Danil should send the answer to his boss using Workforces messages.

A subtree of vertex v is a set of vertices for which the shortest path from them to the root passes through v. In particular, the vertex v is in the subtree of v.

Danil is not going to perform his duties. He asks you to write a program, which answers the boss instead of him.

Input

The first line contains a single integer n (1 ≤ n ≤ 200 000) — the number of vertices in the tree.

The second line contains n - 1 space-separated integers p2, p3, ..., pn (1 ≤ pi < i), where pi is the ancestor of vertex i.

The third line contains n space-separated integers t1, t2, ..., tn (0 ≤ ti ≤ 1), where ti is 1, if the light is turned on in vertex i and 0 otherwise.

The fourth line contains a single integer q (1 ≤ q ≤ 200 000) — the number of tasks.

The next q lines are get v or pow v (1 ≤ v ≤ n) — the tasks described above.

Output

For each task get v print the number of rooms in the subtree of v, in which the light is turned on.

Example

Input

4
1 1 1
1 0 0 1
9
get 1
get 2
get 3
get 4
pow 1
get 1
get 2
get 3
get 4

Output

2
0
0
1
2
1
1
0

Note

The tree before the task pow 1.

The tree after the task pow 1.

#include<iostream>
#include<algorithm>
#include<string>
#include<map>//int dx[4]={0,0,-1,1};int dy[4]={-1,1,0,0};
#include<set>//int gcd(int a,int b){return b?gcd(b,a%b):a;}
#include<vector>
#include<cmath>
#include<stack>
#include<string.h>
#include<stdlib.h>
#include<cstdio>
#define mod 1e9+7
#define ll long long
#define maxn 200005
#define MAX 500005
#define ms memset
using namespace std;
#pragma comment(linker, "/STACK:1024000000,1024000000") ///在c++中是防止暴栈用的
struct node
{
    int e,next;
    node(int x=0,int y=0)
    {
        e=x;
        next=y;
    }
}edge[maxn<<1];
/*
题目大意:给定一个树形系统,
两种操作:一种变换子树的暗亮,
一种查询子树的亮灯的个数。

一般观察数据量是线段树没跑了。
又是一道用dfs序维护线段树的题目。
用线段树维护的是区间和。
还是老样子,在dfs序中区间的包含关系是就是子节点关系,
把握了这一点建树就好办了,当然,涉及区间维护的肯定离不开懒惰标记了。
*/
int n,x,q;
int tot,ti;
vector<int> vt[maxn];
int pl[maxn],pr[maxn],sum[maxn<<2],lazy[maxn<<2];
int a[maxn],cnt;
int light[maxn];///数据数组

void init()
{
    for(int i=0;i<maxn;i++)    vt[i].clear();
   ///memset(head,-1,sizeof(head));
   tot=0;
   ti=0;
}

void add_edge(int a,int b)
{
    vt[a].push_back(b);
}

void dfs(int u,int fa)
{
    pl[u]=++ti;
    a[ti]=u;///附加映射关系
    int len=vt[u].size();
    for(int i=0;i<len;i++)
    {
        int v=vt[u][i];
        if(v==fa) continue;
        dfs(v,u);
    }
    pr[u]=ti;
    ///cout<<u<<" "<<pl[u]<<" "<<pr[u]<<endl;
}///将dfs产生的序列区间都封装在pl和pr数组中

void pushup(int rt)
{
    sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}

void pushdown(int rt,int lsum,int rsum)
{
    if(lazy[rt])
    {
        lazy[rt<<1]^=1;
        lazy[rt<<1|1]^=1;
        sum[rt<<1]=lsum-sum[rt<<1];
        sum[rt<<1|1]=rsum-sum[rt<<1|1];
        lazy[rt]=0;
    }
}

void Build(int l,int r,int rt)
{
    lazy[rt]=0;
    if(l==r)
    {
        sum[rt]=light[a[l]];
        return ;
    }
    int mid=(l+r)>>1;
    pushdown(rt,mid-l+1,r-mid);
    Build(l,mid,rt<<1);
    Build(mid+1,r,rt<<1|1);
    pushup(rt);
}

void update(int l,int r,int rt,int L,int R)
{
    if(L<=l&&r<=R)
    {
        sum[rt]=r-l+1-sum[rt];//变换颜色
        lazy[rt] ^= 1;
        return ;
    }
    int mid=(l+r)>>1;
    pushdown(rt,mid-l+1,r-mid);
    if(L<=mid) update(l,mid,rt<<1,L,R);
    if(mid<R) update(mid+1,r,rt<<1|1,L,R);
    pushup(rt);
}

int query(int l,int r,int rt,int L,int R)
{
    if( L<=l && r<=R )  return sum[rt];
    int mid=(l+r)>>1 , ret = 0;
    pushdown(rt,mid-l+1,r-mid);
    if(mid>=L)   ret+= query(l,mid,rt<<1,L,R);
    if(mid<R)     ret+= query(mid+1,r,rt<<1|1,L,R);
    return ret;
}

int main()
{
    init();
    scanf("%d",&n);
    for(int i=2;i<=n;i++)
    {
        scanf("%d",&x);
        add_edge(i,x);
        add_edge(x,i);
    }

    for(int i=1;i<=n;i++) scanf("%d",&light[i]);

    dfs(1,-1);Build(1,ti,1);

    scanf("%d",&q);
    char s[5];
    for(int i=0;i<q;i++)
    {
         scanf("%s%d",s,&x);
         if(s[0]=='g')   printf("%d\n",query(1,ti,1,pl[x],pr[x]) );
         else update(1,ti,1,pl[x],pr[x]);
     }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37451344/article/details/81125549