Codeforces Round #502 (in memory of Leopoldo Taravilse, Div. 1 + Div. 2) G. The Tree
3 seconds
256 megabytes
standard input
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:
- If vertex vv is white, mark it as black; otherwise, perform this operation on all direct sons of vv instead.
- Mark all vertices in the subtree of vv (including vv) as white.
- 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?
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.
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的更多相关文章
- 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 ...
- Codeforces Round #502 (in memory of Leopoldo Taravilse, Div. 1 + Div. 2)
第一次参加cf的比赛 有点小幸运也有点小遗憾 给自己定个小目标 1500[对啊我就是很菜qvq A. The Rank 难度:普及- n位学生 每个学生有四个分数 然鹅我们只需要知道他的分数和 按分数 ...
- Codeforces Round #502 (in memory of Leopoldo Taravilse, Div. 1 + Div. 2) E. The Supersonic Rocket
这道题比赛之后被重新加了几个case,很多人现在都过不了了 算法就是先求凸包,然后判断两个凸包相等 我们可以吧凸包序列化为两点距离和角度 角度如果直接拿向量的叉积是不对的,,因为钝角和锐角的叉积有可能 ...
- 【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 ...
- Codeforces Round #502
Codeforces Round #502 C. The Phone Number 题目描述:求一个\(n\)排列,满足\(LIS+LDS\)最小 solution 枚举\(LIS\),可证明\(LD ...
- 【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 ...
- Codeforces Round #195 A B C 三题合集 (Div. 2)
A 题 Vasily the Bear and Triangle 题目大意 一个等腰直角三角形 ABC,角 ACB 是直角,AC=BC,点 C 在原点,让确定 A 和 B 的坐标,使得三角形包含一个矩 ...
- cf之路,1,Codeforces Round #345 (Div. 2)
cf之路,1,Codeforces Round #345 (Div. 2) ps:昨天第一次参加cf比赛,比赛之前为了熟悉下cf比赛题目的难度.所以做了round#345连试试水的深浅..... ...
- 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 ...
随机推荐
- Tickets HDU1260
题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=1260 (http://www.fjutacm.com/Problem.jsp?pid=1382) 题意 ...
- 我应该记录一下我不太了解的一些c语言函数
当然,现在还不分类 fmemopen getpagesize()
- 【划水闲谈】Terraria 1.3.5更新
我知道这本应是一个算法博客,但又有谁规定了不能发点其他内容呢? Terraria,一个有趣的沙盒游戏.在这里,你可以建造,挖掘,开始一次又一次新的冒险. 4月19日,Re-Logic承诺的官方中文版终 ...
- 关于oracle数据库死锁的检查方法
一.数据库死锁的现象程序在执行的过程中,点击确定或保存按钮,程序没有响应,也没有出现报错. 二.死锁的原理当对于数据库某个表的某一列做更新或删除等操作,执行完毕后该条语句不提交,另一条对于这一列数据做 ...
- Python3 item系列
一.前言 #在python中一切皆对象 ''' 创建了一个dict实例-->dic就是dict的实例对象 我们通过dic['k1']可以得到k1所对应的值 那么我们自定义一个类,可不可以使用对象 ...
- angular4.0和angularJS、react.js、vue.js的简单比较
angularJS特性 模板功能强大丰富(数据绑定大大减少了代码量) 比较完善的前端MVC框架(只要学习这个框架,按照规定往里面填东西就可以完成前端几乎所有的的问题) 引入了Java的一些概念 ang ...
- Java项目打war包的方法
我们可以运用DOS命令来手工打war包: 首先,打开DOS命令行,敲入“jar”,我们发现它提示不是内部或外部的命令这样的错误,这时八成是你的JAVA环境没有配置好,我们可以用JAVA_HOME方式或 ...
- 洛谷P2422 良好的感觉
题目意思就是:最大化一个区间的和与这个区间的最小值的乘积. 换一个角度看问题,如果我们穷举一个最小值 $ a_i $ ,然后往左右扩展,显然是对的,复杂度 $ O(n^2) $.所以我们要优化一下这个 ...
- session的本质及如何实现共享?
为什么有session? 首先大家知道,http协议是无状态的,即你连续访问某个网页100次和访问1次对服务器来说是没有区别对待的,因为它记不住你. 那么,在一些场合,确实需要服务器记住当前用户怎么办 ...
- Unix IPC之读写锁
linux中读写锁的rwlock介绍 读写锁比mutex有更高的适用性,可以多个线程同时占用读模式的读写锁,但是只能一个线程占用写模式的读写锁: 1,当读写锁是写加锁状态时, 在这个锁被解锁之前, 所 ...