CF1017G The Tree

LG传送门

树链剖分好题。

乍一看还以为是道沙比题,然后发现修改操作有点不一样。

但是如果你对基本操作还不太熟练,可以看看我的树链剖分总结

有三个操作:

  1. 从一个点往下染黑,是黑色节点就继续染,一直染到白色节点为止;
  2. 染白一棵子树;
  3. 查询一个点的颜色。

主要是第一个操作不好处理。由于每次只询问一个点的信息,考虑把一个点的颜色用从根节点到这个点的最大后缀和来表达:最大后缀和小于零则为白色,反之则为黑色。首先把树上每一个点的权值都定为\(-1\),对于每个1操作,把该点的权值++;对于每个2操作,把一棵子树的权值全都变成\(-1\),并在该子树的根节点减去一个权值,使得大树根节点到子树根节点的最大后缀和恰为\(-1\);对于3查询,查询一个根节点到这个点的最大后缀和,\(<0\)白色,\(\ge 0\)黑色。可以证(shou)明(wan),这样做正确地在\(O(n(log n)^2)\)的复杂度内维护了树上的信息。

如果你不会在树上维护最大后缀和,可以先考虑在区间上维护,用线段树维护一个区间和、一个区间最大后缀和就好了,合并信息的方法就很容易看出了,查询的时候也可以用同样的方法合并,放到树上来之后合并的方法还是没有变。

#include<cstdio>
#include<cctype>
#define R register
#define I inline
using namespace std;
const int S=200003,M=800003,inf=0x3f3f3f3f;
char buf[1000000],*p1,*p2;
I char gc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,S,stdin),p1==p2)?EOF:*p1++;}
I int rd(){
R int f=0; R char c=gc();
while(c<48||c>57) c=gc();
while(c>47&&c<58) f=f*10+(c^48),c=gc();
return f;
}
struct O{int f,g;};
struct N{int f,g,b;}a[M];
int h[S],s[S],g[S],d[S],t[S],p[S],q[S],r[S],f[S],c,e,n;
I int max(int x,int y){return x>y?x:y;}
O operator+(O x,O y){return (O){max(x.f+y.g,y.f),x.g+y.g};}
I void add(int x,int y){s[++c]=h[x],h[x]=c,g[c]=y;}
I void upd(int k,int l,int r){a[k].f=-1,a[k].g=-(r-l+1),a[k].b=1;}
I void psu(int k,int p,int q){a[k].f=max(a[q].f,a[p].f+a[q].g),a[k].g=a[p].g+a[q].g;}
I void psd(int k,int l,int r){
if(a[k].b){
R int p=k<<1,q=p|1,m=l+r>>1;
upd(p,l,m),upd(q,m+1,r),a[k].b=0;
}
}
void bld(int k,int l,int r){
if(l==r){a[k].f=a[k].g=-1; return ;}
R int p=k<<1,q=p|1,m=l+r>>1;
bld(p,l,m),bld(q,m+1,r),psu(k,p,q);
}
void mdf1(int k,int l,int r,int x,int v){
if(l==r){a[k].f+=v,a[k].g+=v; return ;}
R int p=k<<1,q=p|1,m=l+r>>1;
psd(k,l,r);
if(x<=m) mdf1(p,l,m,x,v);
else mdf1(q,m+1,r,x,v);
psu(k,p,q);
}
void mdf2(int k,int l,int r,int x,int y){
if(x<=l&&r<=y){upd(k,l,r); return ;}
R int p=k<<1,q=p|1,m=l+r>>1;
psd(k,l,r);
if(x<=m) mdf2(p,l,m,x,y);
if(m<y) mdf2(q,m+1,r,x,y);
psu(k,p,q);
}
O qry(int k,int l,int r,int x,int y){
if(x<=l&&r<=y) return (O){a[k].f,a[k].g};
R int p=k<<1,q=p|1,m=l+r>>1;
O o=(O){-inf,0};
psd(k,l,r);
if(x<=m) o=o+qry(p,l,m,x,y);
if(m<y) o=o+qry(q,m+1,r,x,y);
return o;
}
void dfs1(int x,int f){
d[x]=d[f]+1,p[x]=f,t[x]=1;
for(R int i=h[x],y,m=0;i;i=s[i])
if((y=g[i])^f){
dfs1(y,x),t[x]+=t[y];
if(t[y]>m) q[x]=y,m=t[y];
}
}
void dfs2(int x,int t){
f[x]=++e,r[x]=t;
if(q[x]) dfs2(q[x],t);
for(R int i=h[x],y;i;i=s[i])
if((y=g[i])^p[x]&&y^q[x])
dfs2(y,y);
}
I int qry0(int x){
R int o=-inf,v=0; O u;
while(x)
u=qry(1,1,n,f[r[x]],f[x]),o=max(o,u.f+v),v+=u.g,x=p[r[x]];
return o;
}
int main(){
R int Q,i,x,y;
for(n=rd(),Q=rd(),i=2;i<=n;++i)
x=rd(),add(x,i);
dfs1(1,0),dfs2(1,1),bld(1,1,n);
for(i=1;i<=Q;++i){
x=rd(),y=rd();
if(x==1)
mdf1(1,1,n,f[y],1);
if(x==2)
mdf2(1,1,n,f[y],f[y]+t[y]-1),mdf1(1,1,n,f[y],-(qry0(y)+1));
if(x==3)
qry0(y)>=0?printf("black\n"):printf("white\n");
}
return 0;
}

跑的还算快。

CF1017G The Tree 树链剖分的更多相关文章

  1. [CF1017G]The Tree[树链剖分+线段树]

    题意 给一棵一开始 \(n\) 个点全是白色的树,以 \(1\) 为根,支持三种操作: 1.将某一个点变黑,如果已经是黑色则该操作对所有儿子生效. 2.将一棵子树改成白色. 3.询问某个点的颜色. \ ...

  2. Hdu 5274 Dylans loves tree (树链剖分模板)

    Hdu 5274 Dylans loves tree (树链剖分模板) 题目传送门 #include <queue> #include <cmath> #include < ...

  3. POJ3237 Tree 树链剖分 边权

    POJ3237 Tree 树链剖分 边权 传送门:http://poj.org/problem?id=3237 题意: n个点的,n-1条边 修改单边边权 将a->b的边权取反 查询a-> ...

  4. Query on a tree——树链剖分整理

    树链剖分整理 树链剖分就是把树拆成一系列链,然后用数据结构对链进行维护. 通常的剖分方法是轻重链剖分,所谓轻重链就是对于节点u的所有子结点v,size[v]最大的v与u的边是重边,其它边是轻边,其中s ...

  5. 【BZOJ-4353】Play with tree 树链剖分

    4353: Play with tree Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 31  Solved: 19[Submit][Status][ ...

  6. SPOJ Query on a tree 树链剖分 水题

    You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...

  7. poj 3237 Tree 树链剖分

    题目链接:http://poj.org/problem?id=3237 You are given a tree with N nodes. The tree’s nodes are numbered ...

  8. Codeforces Round #200 (Div. 1) D Water Tree 树链剖分 or dfs序

    Water Tree 给出一棵树,有三种操作: 1 x:把以x为子树的节点全部置为1 2 x:把x以及他的所有祖先全部置为0 3 x:询问节点x的值 分析: 昨晚看完题,马上想到直接树链剖分,在记录时 ...

  9. poj 3237 Tree 树链剖分+线段树

    Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...

随机推荐

  1. 关于easyUI的一些js方法

    1. $("#dg").datagrid("load",{ "userName":$("#s_userName").va ...

  2. [翻译] GoogleMaterialDesignIcons

    GoogleMaterialDesignIcons Google Material Design Icons Font for iOS GMD图片样式的字体,用于iOS开发. It is based ...

  3. Top 25 Most Frequently Asked Interview Core Java Interview Questions And Answers

    We are sharing 25 java interview questions , these questions are frequently asked by the recruiters. ...

  4. linux中ftp提示--553 Could not create file

    今天在阿里云的linux上搭建ftp服务的时候,搭建成功之后,上传文件时总提示553 Could not create file,找了半天原因,终于解决了 ftp主目录为/home/myftp /ho ...

  5. Provisional headers are shown

    问题: Chrome请求出现"Provisional headers are shown": 原因: 这种一般是由于浏览器端的插件或客户端的软件对请求进行了拦截:我们出现的情况,是 ...

  6. CSS学习摘要-盒子模型

    注:全文摘要自网络开发者网站,当然间隔也会整理一些思路和格式排版添加进去. CSS框模型(译者注:也被称为"盒模型")是网页布局的基础 --每个元素被表示为一个矩形的方框,框的内容 ...

  7. 洛谷 P1251 餐巾计划问题(线性规划网络优化)【费用流】

    (题外话:心塞...大部分时间都在debug,拆点忘记加N,总边数算错,数据类型标错,字母写错......) 题目链接:https://www.luogu.org/problemnew/show/P1 ...

  8. 理解JVM——JVM的结构

    这是理解JVM的第一篇文章,这篇文章主要介绍JVM的总体结构和每一个部分的功能.内容比较少,对于每一个部分详细的内容,放到后面的文章中,逐步展开.这个系列总结完,应该会对JVM有一个整体且深入的认识了 ...

  9. mycat结合双主复制实现读写分离模式

    简介:应用程序仅需要连接mycat,后端服务器的读写分离由mycat进行控制,后端服务器数据的同步由MySQL主从同步进行控制. 本次实验环境架构图 服务器主机规划 主机名 IP  功能 备注 lin ...

  10. Js 运行机制 event loop

    Js - 运行机制 (Even Loop) Javascript 的单线程 - 引用思否的说法: JavaScript的一个语言特性(也是这门语言的核心)就是单线程.什么是单线程呢?简单地说就是同一时 ...