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\n",ans);
}
}
return 0;
}

Codeforces Round #877 (Div. 2) E. Danil and a Part-time Job的更多相关文章

  1. Codeforces Round #877 (Div. 2) D. Olya and Energy Drinks

    题目链接:http://codeforces.com/contest/877/problem/D D. Olya and Energy Drinks time limit per test2 seco ...

  2. Codeforces Round #877 (Div. 2) B. - Nikita and string

    题目链接:http://codeforces.com/contest/877/problem/B Nikita and string time limit per test2 seconds memo ...

  3. Codeforces Round #442 (Div. 2) E Danil and a Part-time Job (dfs序加上一个线段树区间修改查询)

    题意: 给出一个具有N个点的树,现在给出两种操作: 1.get x,表示询问以x作为根的子树中,1的个数. 2.pow x,表示将以x作为根的子树全部翻转(0变1,1变0). 思路:dfs序加上一个线 ...

  4. Codeforces Round #366 (Div. 2) ABC

    Codeforces Round #366 (Div. 2) A I hate that I love that I hate it水题 #I hate that I love that I hate ...

  5. Codeforces Round #354 (Div. 2) ABCD

    Codeforces Round #354 (Div. 2) Problems     # Name     A Nicholas and Permutation standard input/out ...

  6. Codeforces Round #368 (Div. 2)

    直达–>Codeforces Round #368 (Div. 2) A Brain’s Photos 给你一个NxM的矩阵,一个字母代表一种颜色,如果有”C”,”M”,”Y”三种中任意一种就输 ...

  7. cf之路,1,Codeforces Round #345 (Div. 2)

     cf之路,1,Codeforces Round #345 (Div. 2) ps:昨天第一次参加cf比赛,比赛之前为了熟悉下cf比赛题目的难度.所以做了round#345连试试水的深浅.....   ...

  8. Codeforces Round #279 (Div. 2) ABCDE

    Codeforces Round #279 (Div. 2) 做得我都变绿了! Problems     # Name     A Team Olympiad standard input/outpu ...

  9. Codeforces Round #262 (Div. 2) 1003

    Codeforces Round #262 (Div. 2) 1003 C. Present time limit per test 2 seconds memory limit per test 2 ...

随机推荐

  1. 新生代内存中为什么要有两个survivor区

    首先是关于新生代中的内存分布的描述: 新生代中的对象都是“朝生夕死”的对象,所以每次gc存活的对象很少,于是在新生代中采用的垃圾回收算法是“复制算法”. 将新生代的内存分为一块较大的Eden区域和两块 ...

  2. 使用express+mongoDB搭建多人博客 学习(2)路由与模板

    修改index.js路由规则: var express = require('express'); var router = express.Router(); /* GET home page. * ...

  3. Java基础之入门介绍

    基础知识 1.JVM.JRE和JDK的区别:     JVM(Java Virtual Machine):java虚拟机,用于保证java的跨平台的特性.                   java ...

  4. react中的context的基础用法

    context提供了一种数据共享的机制,里面有两个关键概念——provider,consumer,下面做一些key features描述. 参考网址:https://react.docschina.o ...

  5. php后端程序开发学习网站梳理

    博主只列举自己经常用到的: 看教学视频:慕课网,网易云课堂,百度传课 看博文和知识点:csdn 看源码:github 刷题:codewars 学习框架:thinkphp官网 下载相关资源:csdn 看 ...

  6. git处理时的问题

    1. 在node.js开发的时候常常会遇到从别人的远程仓库中clone时出现文件名过长的错误, 或则是在本地npm下载之后的文件进行上传到自己的远程仓库的时候会出现 File too long的情况, ...

  7. Visual SVN IIS反向代理设置

    需要解决的问题: 1. 设置反向代理 2. 解决部分后缀文件无法提交的问题 1. 设置反向代理 接收所有的URL 允许所有的HTTP_HOST 跳转到被代理的服务器 2. 允许所有后缀的文件访问IIS ...

  8. github入门之配置github本地仓库--2

    *前期准备工作 创建github账户 github地址 1.设置SSH_Key ssh-keygen -t rsa -C "你的邮箱" 2.查看秘钥 cat ~/.ssh/id_r ...

  9. win10下vs2013为程序集新建强名称文件时“未能完成操作。拒绝访问”的解决方案

    昨日,在使用vs2013开发开发一个小工具,打算给这个小工具的源代码进行保护. 在输入完成建立强名称密钥文件时,爆出了如下错误: 一开始以为是项目所在路径的权限问题,于是给项目所在路径文件夹添加了“U ...

  10. LeetCode 3Sum Closest 最近似的3sum(2sum方法)

    题意:找到最接近target的3个元素之和,并返回该和. 思路:用2个指针,时间复杂度O(n^2). int threeSumClosest(vector<int>& nums, ...