G. The Tree
time limit per test

3 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Abendsen assigned a mission to Juliana. In this mission, Juliana has a rooted tree with nn vertices. Vertex number 11 is the root of this tree. Each vertex can be either black or white. At first, all vertices are white. Juliana is asked to process qq queries. Each query is one of three types:

  1. If vertex vv is white, mark it as black; otherwise, perform this operation on all direct sons of vv instead.
  2. Mark all vertices in the subtree of vv (including vv) as white.
  3. Find the color of the ii-th vertex.

An example of operation "1 1" (corresponds to the first example test). The vertices 11 and 22 are already black, so the operation goes to their sons instead.

Can you help Juliana to process all these queries?

Input

The first line contains two integers nn and qq (2≤n≤1052≤n≤105, 1≤q≤1051≤q≤105) — the number of vertices and the number of queries.

The second line contains n−1n−1 integers p2,p3,…,pnp2,p3,…,pn (1≤pi<i1≤pi<i), where pipi means that there is an edge between vertices ii and pipi.

Each of the next qq lines contains two integers titi and vivi (1≤ti≤31≤ti≤3, 1≤vi≤n1≤vi≤n) — the type of the ii-th query and the vertex of the ii-th query.

It is guaranteed that the given graph is a tree.

Output

For each query of type 33, print "black" if the vertex is black; otherwise, print "white".


题意:给你一颗树,树上一开始点的颜色全是白色。然后有三种操作:1.把一个白色的点v染成黑色,如果该点v本就是黑色,则对他的所有直接子节点做操作1。2.将节点v的子树全部染成白色。3.查询节点v的颜色。对于每个操作3输出其颜色。

题解:我们要使其在一个尽量平均的时间内进行求解,就需要将其改造成一个相对平衡的树,那我们就考虑用树链刨分对这颗树进行分解。我们发觉每个操作1对应使该点所在的一条重链所对应的区间黑色区间右端点后移一位,其他影响到的重链也后移一位。因此我们查询点v是否为黑色,就看从根到v点的所有链对应的区间上,任何黑色区间右端点位移位置是否超过该点v。我们对线段树维护两个值,一个是端点对应区间剩余白色点的个数leaf(可为负数,即透支后面的链的白色点数),另一个是对应区间中最靠右侧的黑色区间的右端点超出该区间右端点距离(也就是我们上文说到的对其他重链的影响长度)execr,一开始是-1因为右端点还是白色。剩余白色点的转移就是子区间白色点数相加,而第二个维护量execr(即向区间右端点后边区间的影响长度)的转移则是max(右子区间execr,左子区间execr-右子区间leaf)。这样我们查询的时候就能通过该点向后影响长度来查询该点是不是被染成黑色。>=0就是被染色了,-1则是未染色。对于操作1,直接对对应的线段树上的单点v的区间的execr++,leaf--。对于操作3,我们将根节点到节点v的所有区间连起来,算算execr是不是>-1,若是则染色了。对于操作2,我们则直接把所有对应的区间清0,即leaf为区间点数,execr为-1。为了防止v的祖先节点对v子树区间的影响,我们对v做操作3查询超出长度k,若>-1,则反向对v点做操作1(k+1)次,即execr-=(k+1),leaf+=(k+1)。

 #include<bits/stdc++.h>
#define clr(x) memset(x,0,sizeof(x))
#define clr_1(x) memset(x,-1,sizeof(x))
#define INF 0x3f3f3f3f
#define LL long long
#define pb push_back
#define ls(i) (i<<1)
#define rs(i) (i<<1|1)
#define mp make_pair
#define fi first
#define se second
#define mod 1000000007
using namespace std;
const int N=2e5+;
vector<int> e[N];
int fa[N];
struct seg
{
int l,r,execr,leaf;
bool tag;
}tree[N<<];
int n,m,k,q;
int t,v;
void pushup(int i)
{
tree[i].leaf=tree[i<<].leaf+tree[i<<|].leaf;
tree[i].execr=max(tree[i<<|].execr,tree[i<<].execr-tree[i<<|].leaf);
return ;
}
void init(int i,int l,int r)
{
tree[i]=(seg){l,r,-,,false};
if(l==r)
return ;
int mid=l+r>>;
init(i<<,l,mid);
init(i<<|,mid+,r);
pushup(i);
return ;
}
int top[N],son[N],pre[N],las[N],stot[N],dep[N];
int tot;
void dfs1(int u,int f,int deep)
{
stot[u]=;
dep[u]=deep;
fa[u]=f;
for(auto p:e[u])
{
if(p==f) continue;
dfs1(p,u,deep+);
stot[u]+=stot[p];
if(son[u]== || stot[son[u]]<stot[p])
son[u]=p;
}
return ;
}
void dfs2(int u,int tp)
{
pre[u]=++tot;
top[u]=tp;
if(son[u]) dfs2(son[u],tp);
for(auto p:e[u])
{
if(p==son[u] || p==fa[u])
continue;
dfs2(p,p);
}
las[u]=tot;
return ;
}
void pushdown(int i)
{
if(tree[i].l!=tree[i].r)
{
tree[i<<].tag=tree[i<<|].tag=;
tree[i<<].leaf=tree[i<<].r-tree[i<<].l+,tree[i<<].execr=-;
tree[i<<|].leaf=tree[i<<|].r-tree[i<<|].l+,tree[i<<|].execr=-;
}
tree[i].tag=;
return ;
}
void update(int i,int l,int r,int val)
{
if(tree[i].l>=l && tree[i].r<=r)
{
if(val==INF)//都是区间修改
tree[i].leaf=tree[i].r-tree[i].l+,tree[i].execr=-,tree[i].tag=;
else
tree[i].leaf-=val,tree[i].execr+=val,tree[i].tag=;//都是单点修改
return ;
}
if(tree[i].tag) pushdown(i);
int mid=tree[i].l+tree[i].r>>;
if(l<=mid) update(i<<,l,r,val);
if(r>mid) update(i<<|,l,r,val);
pushup(i);
return ;
}
struct ret{
int execr,leaf;
};
ret operator + (const ret &a,const ret &b)
{
ret c;
c.leaf=a.leaf+b.leaf;
c.execr=max(b.execr,a.execr-b.leaf);
return c;
}
ret query(int i,int l,int r)
{
if(tree[i].l>=l && tree[i].r<=r)
return (ret){tree[i].execr,tree[i].leaf};
if(tree[i].tag) pushdown(i);
int mid=tree[i].l+tree[i].r>>;
ret retur=(ret){-INF,};
if(r>mid) retur=query(i<<|,l,r)+retur;
if(l<=mid) retur=query(i<<,l,r)+retur;
return retur;
}
int que(int x)
{
int tx=top[x];
ret retur=(ret){-INF,},per;
while(tx!=)
{
per=query(,pre[tx],pre[x]);
retur=per+retur;
x=fa[tx],tx=top[x];
}
per=query(,pre[tx],pre[x]);
retur=per+retur;
return retur.execr;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie();
cout.tie();
cin>>n>>q;
for(int i=;i<=n;i++)
{
cin>>v;
e[v].pb(i);
e[i].pb(v);
}
init(,,n);
dfs1(,,);
dfs2(,);
for(int i=;i<=q;i++)
{
cin>>t>>v;
if(t==)
update(,pre[v],pre[v],);
else if(t==)
{
update(,pre[v],las[v],INF);
t=que(v);
if(t>-)
update(,pre[v],pre[v],-(t+));
}
else if(t==)
{
t=que(v);
cout<<(t>-?"black":"white")<<endl;
}
}
return ;
}

Codeforces Round #502 (in memory of Leopoldo Taravilse, Div. 1 + Div. 2) G. The Tree的更多相关文章

  1. E. The Supersonic Rocket Codeforces Round #502 (in memory of Leopoldo Taravilse, Div. 1 + Div. 2)

    http://codeforces.com/contest/1017/problem/E 凸包模板+kmp #include <cstdio> #include <cstdlib&g ...

  2. Codeforces Round #502 (in memory of Leopoldo Taravilse, Div. 1 + Div. 2)

    第一次参加cf的比赛 有点小幸运也有点小遗憾 给自己定个小目标 1500[对啊我就是很菜qvq A. The Rank 难度:普及- n位学生 每个学生有四个分数 然鹅我们只需要知道他的分数和 按分数 ...

  3. Codeforces Round #502 (in memory of Leopoldo Taravilse, Div. 1 + Div. 2) E. The Supersonic Rocket

    这道题比赛之后被重新加了几个case,很多人现在都过不了了 算法就是先求凸包,然后判断两个凸包相等 我们可以吧凸包序列化为两点距离和角度 角度如果直接拿向量的叉积是不对的,,因为钝角和锐角的叉积有可能 ...

  4. 【Codeforces Round #502 (in memory of Leopoldo Taravilse, Div. 1 + Div. 2) D】The Wu

    [链接] 我是链接,点我呀:) [题意] 给你n个字符串放在multiset中. 这些字符串都是长度为m的01串. 然后给你q个询问 s,k 问你set中存在多少个字符串t 使得∑(t[i]==s[i ...

  5. Codeforces Round #502

    Codeforces Round #502 C. The Phone Number 题目描述:求一个\(n\)排列,满足\(LIS+LDS\)最小 solution 枚举\(LIS\),可证明\(LD ...

  6. 【Codeforces Round #502 (Div. 1 + Div. 2) 】

    A:https://www.cnblogs.com/myx12345/p/9843032.html B:https://www.cnblogs.com/myx12345/p/9843050.html ...

  7. Codeforces Round #195 A B C 三题合集 (Div. 2)

    A 题 Vasily the Bear and Triangle 题目大意 一个等腰直角三角形 ABC,角 ACB 是直角,AC=BC,点 C 在原点,让确定 A 和 B 的坐标,使得三角形包含一个矩 ...

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

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

  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. 【Python学习笔记】Jupyter Lab目录插件安装

    Jupyter Lab目录插件安装 当然首先你得有python和已经安装了jupyter lab. 1 安装jupyter_contrib_nbextensions 首先先安装jupyter_cont ...

  2. MyEclipse文本对比界面样式修改

    MyEclipse刚安装好,使用文件对比的时候,发现两边的对比颜色非常浅,不同的地方不容易发现,可以通过以下配置将显示颜色调深一点. 配置 效果

  3. Vue.js 基础快速入门

    Vue.js是一个JavaScript MVVM库,它是以数据驱动和组件化的思想构建的.Vue.js提供了简洁.易于理解的API,使得我们能够快速地上手并使用Vue.js 如果之前已经习惯了用jQue ...

  4. python+selenium第一步 - 环境搭建

    刚开始学习一门技术,肯定是要从环境搭建开始的,我也不例外. 首先选择需要安装的版本,我使用的是mac自带的2.7版本. selenium2,和火狐浏览器 为求稳定不会出现未知问题,我选择了seleni ...

  5. [android]解析XML文件的方法有三种:PULL,DOM,SAM

    PULL 的工作原理: XML pull提供了开始元素和结束元素.当某个元素开始时,可以调用parser.nextText从XML文档中提取所有字符数据.当解析到一个文档结束时,自动生成EndDocu ...

  6. AARRR:数据运营模型

    一.基础知识 产品经理  <增长黑客>数据分析基础 -- 获取(Acquisition)-- 激活(Activation)-- 留存(Retention)-- 收入(Revenue)-- ...

  7. Java测试框架Mockito源码分析

    1.Mockito简介 测试驱动的开发(Test Driven Design, TDD)要求我们先写单元测试,再写实现代码.在写单元测试的过程中,一个很普遍的问题是,要测试的类会有很多依赖,这些依赖的 ...

  8. 专业分析docker的分层存储技术

    话不在多,指明要点! 联合挂载是用于将多个镜像层的文件系统挂载到一个挂载点来实现一个统一文件系统视图的途径, 是下层存储驱动(aufs.overlay等) 实现分层合并的方式. 所以严格来说,联合挂载 ...

  9. Chrome-Adobe Flash 无法正常使用

    https://support.google.com/chrome/answer/6258784 该网站因是是google.com,被强了,所以一般打不开. 故将google官方说明记录以下: 如果 ...

  10. CCF CSP 201604-3 路径解析

    CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201604-3 路径解析 问题描述 在操作系统中,数据通常以文件的形式存储在文件系统中.文件系 ...