CF1017G The Tree 树链剖分
CF1017G The Tree
树链剖分好题。
乍一看还以为是道沙比题,然后发现修改操作有点不一样。
但是如果你对基本操作还不太熟练,可以看看我的树链剖分总结
有三个操作:
- 从一个点往下染黑,是黑色节点就继续染,一直染到白色节点为止;
- 染白一棵子树;
- 查询一个点的颜色。
主要是第一个操作不好处理。由于每次只询问一个点的信息,考虑把一个点的颜色用从根节点到这个点的最大后缀和来表达:最大后缀和小于零则为白色,反之则为黑色。首先把树上每一个点的权值都定为\(-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 树链剖分的更多相关文章
- [CF1017G]The Tree[树链剖分+线段树]
题意 给一棵一开始 \(n\) 个点全是白色的树,以 \(1\) 为根,支持三种操作: 1.将某一个点变黑,如果已经是黑色则该操作对所有儿子生效. 2.将一棵子树改成白色. 3.询问某个点的颜色. \ ...
- Hdu 5274 Dylans loves tree (树链剖分模板)
Hdu 5274 Dylans loves tree (树链剖分模板) 题目传送门 #include <queue> #include <cmath> #include < ...
- POJ3237 Tree 树链剖分 边权
POJ3237 Tree 树链剖分 边权 传送门:http://poj.org/problem?id=3237 题意: n个点的,n-1条边 修改单边边权 将a->b的边权取反 查询a-> ...
- Query on a tree——树链剖分整理
树链剖分整理 树链剖分就是把树拆成一系列链,然后用数据结构对链进行维护. 通常的剖分方法是轻重链剖分,所谓轻重链就是对于节点u的所有子结点v,size[v]最大的v与u的边是重边,其它边是轻边,其中s ...
- 【BZOJ-4353】Play with tree 树链剖分
4353: Play with tree Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 31 Solved: 19[Submit][Status][ ...
- SPOJ Query on a tree 树链剖分 水题
You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...
- poj 3237 Tree 树链剖分
题目链接:http://poj.org/problem?id=3237 You are given a tree with N nodes. The tree’s nodes are numbered ...
- Codeforces Round #200 (Div. 1) D Water Tree 树链剖分 or dfs序
Water Tree 给出一棵树,有三种操作: 1 x:把以x为子树的节点全部置为1 2 x:把x以及他的所有祖先全部置为0 3 x:询问节点x的值 分析: 昨晚看完题,马上想到直接树链剖分,在记录时 ...
- poj 3237 Tree 树链剖分+线段树
Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...
随机推荐
- 关于easyUI的一些js方法
1. $("#dg").datagrid("load",{ "userName":$("#s_userName").va ...
- [翻译] GoogleMaterialDesignIcons
GoogleMaterialDesignIcons Google Material Design Icons Font for iOS GMD图片样式的字体,用于iOS开发. It is based ...
- 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. ...
- linux中ftp提示--553 Could not create file
今天在阿里云的linux上搭建ftp服务的时候,搭建成功之后,上传文件时总提示553 Could not create file,找了半天原因,终于解决了 ftp主目录为/home/myftp /ho ...
- Provisional headers are shown
问题: Chrome请求出现"Provisional headers are shown": 原因: 这种一般是由于浏览器端的插件或客户端的软件对请求进行了拦截:我们出现的情况,是 ...
- CSS学习摘要-盒子模型
注:全文摘要自网络开发者网站,当然间隔也会整理一些思路和格式排版添加进去. CSS框模型(译者注:也被称为"盒模型")是网页布局的基础 --每个元素被表示为一个矩形的方框,框的内容 ...
- 洛谷 P1251 餐巾计划问题(线性规划网络优化)【费用流】
(题外话:心塞...大部分时间都在debug,拆点忘记加N,总边数算错,数据类型标错,字母写错......) 题目链接:https://www.luogu.org/problemnew/show/P1 ...
- 理解JVM——JVM的结构
这是理解JVM的第一篇文章,这篇文章主要介绍JVM的总体结构和每一个部分的功能.内容比较少,对于每一个部分详细的内容,放到后面的文章中,逐步展开.这个系列总结完,应该会对JVM有一个整体且深入的认识了 ...
- mycat结合双主复制实现读写分离模式
简介:应用程序仅需要连接mycat,后端服务器的读写分离由mycat进行控制,后端服务器数据的同步由MySQL主从同步进行控制. 本次实验环境架构图 服务器主机规划 主机名 IP 功能 备注 lin ...
- Js 运行机制 event loop
Js - 运行机制 (Even Loop) Javascript 的单线程 - 引用思否的说法: JavaScript的一个语言特性(也是这门语言的核心)就是单线程.什么是单线程呢?简单地说就是同一时 ...