Codeforces Round #877 (Div. 2) E. Danil and a Part-time Job

E. Danil and a Part-time Job

题目链接:http://codeforces.com/contest/877/problem/E

time limit per test2 seconds
memory limit per test256 megabytes
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:

pow v describes a task to switch lights in the subtree of vertex v.
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.
这里写图片描述
这里写图片描述


解题心得:

  1. 题意是给你一个树,每个节点可以点亮,有q次询问,每次可以询问以i为根的子树下面有多少个亮着的节点,也可以反转以i为根的子树下面的节点的状态(上面所述都包括i节点)。
  2. 看题意有点线段树的意思,当是线段树是标准的二叉树,所以需要将这个树进行处理,可以树链剖分,但是就这个题来说可以写个dfs序处理,处理后得到一段一段的区间,每个区间代表一个原节点子树的范围,每个区间的左边界就是二叉树最下面的节点(1-n),而询问每个原节点就是询问二叉树中区间的值,注意lazy标记。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5+100;
struct node
{
    int l,r,sum;
}bitree[maxn*4];
int lef[maxn],rig[maxn];
int lazy[maxn*4];
bool temp[maxn];
vector <int> ve[maxn];

int tot = 1;
//dfs序处理
void dfs(int nod)
{
    lef[nod] = tot;
    for(int i=0;i<ve[nod].size();i++)
    {
        tot++;
        dfs(ve[nod][i]);
    }
    rig[nod] = tot;
}

void pushdown(int nod)
{
    if(!lazy[nod] || bitree[nod].l == bitree[nod].r)
        return ;
    lazy[nod] ^= 1;
    int l = bitree[nod].l;
    int r = bitree[nod].r;
    int mid = (bitree[nod].l + bitree[nod].r )/2;
    bitree[nod<<1].sum = mid-l+1-bitree[nod<<1].sum;
    bitree[nod<<1|1].sum = r-mid-bitree[nod<<1|1].sum;
    lazy[nod<<1] ^= 1;
    lazy[nod<<1|1] ^= 1;
    bitree[nod].sum = bitree[nod<<1].sum + bitree[nod<<1|1].sum;
}

int get_ans(int nod,int l,int r,int L,int R)
{
    pushdown(nod);
    int mid = (L+R)/2;
    if(L>=l && R<=r)
        return bitree[nod].sum;
    else if(mid < l)
        return get_ans(nod<<1|1,l,r,mid+1,R);
    else if(mid >= r)
        return get_ans(nod<<1,l,r,L,mid);
    else
        return get_ans(nod<<1,l,mid,L,mid) + get_ans(nod<<1|1,mid+1,r,mid+1,R);
}

void init_bitree(int nod,int L,int R)
{
    bitree[nod].l = L;
    bitree[nod].r = R;

    if(L == R)
    {
        if(temp[L])
            bitree[nod].sum = 1;
        return ;
    }
    int mid = (L + R) / 2;
    init_bitree(nod<<1|1,mid+1,R);
    init_bitree(nod<<1,L,mid);
    bitree[nod].sum = bitree[nod<<1].sum + bitree[nod<<1|1].sum;
}

//lazy标记
void make_lazy(int nod,int l,int r,int L,int R)
{
    pushdown(nod);
    if(L>=l && R<=r)
    {
        lazy[nod] ^=1;
        bitree[nod].sum = r - l + 1 - bitree[nod].sum;
        return ;
    }
    int mid = (L + R) / 2;
    if(mid >= r)
        make_lazy(nod<<1,l,r,L,mid);
    else if(mid < l)
        make_lazy(nod<<1|1,l,r,mid+1,R);
    else
    {
        make_lazy(nod<<1,l,mid,L,mid);
        make_lazy(nod<<1|1,mid+1,r,mid+1,R);
    }
    bitree[nod].sum = bitree[nod<<1].sum + bitree[nod<<1|1].sum;
}

int main()
{
    memset(bitree,0,sizeof(bitree));
    int n;
    scanf("%d",&n);
    for(int i=2;i<=n;i++)
    {
        int now;
        scanf("%d",&now);
        ve[now].push_back(i);
    }
    dfs(1);
    for(int i=1;i<=n;i++)
    {
        int now;
        scanf("%d",&now);
        if(now)
            temp[lef[i]] = true;
    }
    init_bitree(1,1,n);
    int q;
    scanf("%d",&q);
    while(q--)
    {
        char s[100];
        int Node;
        scanf("%s%d",s,&Node);
        int ans = 0;
        if(s[0] == 'p')
            make_lazy(1,lef[Node],rig[Node],1,n);
        if(s[0] == 'g')
        {
            ans = get_ans(1,lef[Node],rig[Node],1,n);
            printf("%d
",ans);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/GoldenFingers/p/9107255.html