【题解】

  我们可以发现每次修改之后叶子结点到根的路径最多分为两段:一段白色或者黑色,上面接另一段灰色的。二分+倍增找到分界点,然后更新答案即可。

  check的时候只需要判断当前节点对应的叶子结点的区间是否全部为同一种颜色,用树状数组维护所有叶子节点组成的序列的状态即可。

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
#define LL long long
#define rg register
#define N 200010
using namespace std;
int n,m,rt,cnt,ans0,ans1,l[N],r[N],t[N],col[N],dep[N],pos[N],lea[N],p[N][];
vector<int>son[N];
inline int read(){
int k=,f=; char c=getchar();
while(c<''||c>'')c=='-'&&(f=-),c=getchar();
while(''<=c&&c<='')k=k*+c-'',c=getchar();
return k*f;
}
void dfs(int x){
dep[x]=dep[p[x][]]+;
if(!son[x].size()){
if(col[x]==) ans1++;else ans0++;
pos[x]=l[x]=r[x]=++cnt; lea[cnt]=x; return;
}
int cnt0=,cnt1=;
for(rg int i=;i<(int)son[x].size();i++){
dfs(son[x][i]);
l[x]=min(l[x],l[son[x][i]]); r[x]=max(r[x],r[son[x][i]]);
if(!col[son[x][i]]) cnt0++;
else if(col[son[x][i]]==) cnt1++;
}
if(cnt0==(int)son[x].size()) col[x]=,ans0++;
else if(cnt1==(int)son[x].size()) col[x]=,ans1++;
else col[x]=;
}
inline void add(int x,int y){for(;x<=n;x+=x&-x)t[x]+=y;}
inline int query(int x){int ret=;for(;x;x-=x&-x)ret+=t[x];return ret;}
int main(){
memset(l,0x7f,sizeof(l));
memset(r,,sizeof(r));
n=read(); m=read();
for(rg int i=;i<=n;i++){
son[p[i][]=read()].push_back(i);
if(!p[i][]) rt=i;
}
for(rg int i=;i<=n;i++) col[i]=read();
dfs(rt);
// for(rg int i=1;i<=n;i++) printf("[%d %d]\n",l[i],r[i]);
for(rg int j=;j<;j++)
for(rg int i=;i<=n;i++) p[i][j]=p[p[i][j-]][j-];
for(rg int i=;i<=n;i++) add(i,col[lea[i]]);
// printf("%d %d %d\n",ans1,ans0,n-ans0-ans1);
while(m--){
int x=read(),y=x;
if(col[x]){
for(rg int i=;i>=;i--)if(p[y][i]){
int pa=p[y][i],sum=query(r[pa])-query(l[pa]-);
if(sum==r[pa]-l[pa]+) y=pa;
}
ans1-=dep[x]-dep[y]+;
// printf("y=%d\n",y);
add(pos[x],-); y=x;
for(rg int i=;i>=;i--)if(p[y][i]){
int pa=p[y][i],sum=query(r[pa])-query(l[pa]-);
if(sum==) y=pa;
}
ans0+=dep[x]-dep[y]+;
// printf("y=%d\n",y);
}
else{
for(rg int i=;i>=;i--)if(p[y][i]){
int pa=p[y][i],sum=query(r[pa])-query(l[pa]-);
if(sum==) y=pa;
}
ans0-=dep[x]-dep[y]+;
// printf("y=%d\n",y);
add(pos[x],); y=x;
for(rg int i=;i>=;i--)if(p[y][i]){
int pa=p[y][i],sum=query(r[pa])-query(l[pa]-);
if(sum==r[pa]-l[pa]+) y=pa;
}
ans1+=dep[x]-dep[y]+;
// printf("y=%d\n",y);
}
col[x]^=;
printf("%d %d %d\n",ans1,ans0,n-ans0-ans1);
}
return ;
}

noi.ac NOIP2018 全国热身赛 第二场 T3 color的更多相关文章

  1. noi.ac NOIP2018 全国热身赛 第二场 T1 ball

    [题解] 可以发现每次推的操作就是把序列中每个数变为下一个数,再打一个减一标记:而每次加球的操作就是把球的位置加上标记,再插入到合适的位置. 用set维护即可. #include<cstdio& ...

  2. NOIP2018 全国热身赛 第二场 (不开放)

    NOIP2018 全国热身赛 第二场 (不开放) 题目链接:http://noi.ac/contest/26/problem/60 一道蛮有趣的题目. 然后比赛傻逼了. 即将做出来的时候去做别的题了. ...

  3. NOI.AC NOIP2018 全国热身赛 第四场

    心路历程 预计得分:\(0 + 100 +100\) 实际得分:\(10 + 100 + 0\) 神TM T3模数为啥是\(1e9 + 9\)啊啊啊啊,而且我也确实是眼瞎...真是血的教训啊.. T2 ...

  4. noi.ac NOIP2018 全国热身赛 第四场 T1 tree

    [题解] 考虑从小到大枚举边权,按顺序加边. 当前树被分成了若干个联通块,若各个块内的点只能跟块外的点匹配,那么最终的min g(i,pi)一定大于等于当前枚举的边. 判断各个联通块内的点是否全部能跟 ...

  5. noi.ac NOIP2018 全国热身赛 第四场 T2 sort

    [题解] 跟51nod 1105差不多. 二分答案求出第L个数和第R个数,check的时候再套一个二分或者用two pointers. 最后枚举ai在b里面二分,找到所有范围内的数,排序后输出. 注意 ...

  6. NOI.AC NOIP模拟赛 第二场 补记

    NOI.AC NOIP模拟赛 第二场 补记 palindrome 题目大意: 同[CEOI2017]Palindromic Partitions string 同[TC11326]Impossible ...

  7. NOI.AC: NOIP2018 全国模拟赛习题练习

    闲谈: 最后一个星期还是不浪了,做一下模拟赛(还是有点小虚) #30.candy 题目: 有一个人想买糖吃,有两家商店A,B,A商店中第i个糖果的愉悦度为Ai,B商店中第i个糖果的愉悦度为Bi 给出n ...

  8. NOI.AC NOIP模拟赛 第一场 补记

    NOI.AC NOIP模拟赛 第一场 补记 candy 题目大意: 有两个超市,每个超市有\(n(n\le10^5)\)个糖,每个糖\(W\)元.每颗糖有一个愉悦度,其中,第一家商店中的第\(i\)颗 ...

  9. # NOI.AC省选赛 第五场T1 子集,与&最大值

    NOI.AC省选赛 第五场T1 A. Mas的童年 题目链接 http://noi.ac/problem/309 思路 0x00 \(n^2\)的暴力挺简单的. ans=max(ans,xor[j-1 ...

随机推荐

  1. php安装的扩展php -m可以看到,但是phpinfo()看不到,php-fpm关闭了重新打开还是不行?

    问答 问答详情   php安装的扩展php -m可以看到,但是phpinfo()看不到,php-fpm关闭了重新打开还是不行? centos apache linux html php 3.2k 次浏 ...

  2. 题解报告:hdu 1166 敌兵布阵(线段树or树状数组)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166 Problem Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头 ...

  3. NDK(18)eclipse 使用C++ STL

    1.引用库 在Application.mk 中使用 APP_STL := stlport_static 等. APP_ABI := x86 armeabi APP_PLATFORM := androi ...

  4. python_基础部分(1)

    第1章 Python介绍 1.1 基础介绍 l  代码:代码的出现是为了解决生活中的问题 l  编译解释器:目的是让解释器将代码翻译成计算机可识别的语言 l  编程语言:按照一定规则写出来的语言, C ...

  5. 初学Ajax

    AJAX即“Asynchronous Javascript And XML”(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术. AJAX = 异步 JavaScript和 ...

  6. Asp.Net控件的客户端命名

    我们在用ASP.NET写出来的网页,用浏览器来查看生成的客户端代码的时候经常看到这样的代码:GridView1_ctl101_WebUserControl1_webuserControlButton, ...

  7. codeforces_C. Maximum Subrectangle

    http://codeforces.com/contest/1060/problem/C 题意: a.b数组长度分别为n.m.矩阵C,Cij=ai*bj.在C中找到一个子矩阵,该子矩阵所有元素和不大于 ...

  8. cal - 显示一个日历

    总览 cal [-mjy ] [月份 [年份 ] ] 描述 Cal 显示一个简单的日历.. 如果没有指定参数, 则显示当前月份. 选项如下所列: -m 显示星期一作为一周的第一天.. (缺省为星期日. ...

  9. bindtextdomain - 设置 包括 消息条目 的 路径

    总览 (SYNOPSIS) #include <libintl.h> char * bindtextdomain (const char * domainname, const char ...

  10. No-1.第一个 Python 程序

    1. 第一个 HelloWorld 程序 1.1 Python 源程序的基本概念 Python 源程序就是一个特殊格式的文本文件,可以使用任意文本编辑软件做 Python 的开发 Python 程序的 ...