jzoj4918. 【GDOI2017模拟12.9】最近公共祖先 (树链剖分+线段树)
题面



题解
首先,点变黑的过程是不可逆的,黑化了就再也洗不白了
其次,对于\(v\)的祖先\(rt\),\(rt\)能用来更新答案当且仅当\(sz_{rt}>sz_{x}\),其中\(sz\)表示子树中黑点的个数,\(x\)表示\(rt\)走到\(v\)的路径上的第二个节点
每一次染黑一个新的点\(u\)之后,我们要让它所有祖先的\(sz+1\),那么我们可以考虑树链剖分+线段树
再回过头来康康树链剖分的过程啊……我们跳着跳着跳到了\(u\),那么对于\([top[u],u]\)之间的点的\(sz\)全都要\(+1\),所以每一次都是重链的\(top\)到下面某个节点区间加……
那么这么说来这次之后\(son[u]\)的\(sz\)不是绝对小于\(u\)的\(sz\)了么?!
然后我们惊喜的发现,如果有一个点\(v\)从下面往上找根节点的时候既经过\(son[u]\)又经过\(u\),\(u\)节点就可以用来更新答案了!
那么我们每一次染黑节点跳树剖的时候,每一次跳到一个\(u\),就把\(top[u]\)到\(u\)的区间的\(sz\)区间加。我们顺便在线段树上记一个\(mx\)表示区间最大值,一开始所有节点的\(mx\)都是\(-1\),每一次都把\(u\)节点对应的值单点修改成它自己的值。那么查询的时候只要在跳树剖查询\([top[u],fa[u]]\)这个区间的\(mx\)就行了
然而如果父亲与儿子是在不同的重链中该怎么办呢?直接单点查询两个点的\(sz\)然后暴力判断就行了
复杂度\(O(n\log^2n)\)
//minamoto
#include<bits/stdc++.h>
#define R register
#define ls (p<<1)
#define rs (p<<1|1)
#define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
R int res,f=1;R char ch;
while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
return res*f;
}
inline char getop(){R char ch;while((ch=getc())!='M'&&ch!='Q');return ch;}
char sr[1<<21],z[20];int C=-1,Z=0;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
void print(R int x){
if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x;
while(z[++Z]=x%10+48,x/=10);
while(sr[++C]=z[Z],--Z);sr[++C]='\n';
}
const int N=2e5+5;
struct eg{int v,nx;}e[N<<1];int head[N],tot;
inline void add(R int u,R int v){e[++tot]={v,head[u]},head[u]=tot;}
int top[N],dfn[N],sz[N],son[N],fa[N],rk[N],a[N],ok[N],dep[N];
int vis[N<<2],mx[N<<2],tag[N<<2],val[N<<2];
int n,m,res,cnt,x,y,u,v;char ch;
void build(int p,int l,int r){
val[p]=mx[p]=-1;
if(l==r)return mx[p]=rk[l],void();
int mid=(l+r)>>1;
build(ls,l,mid),build(rs,mid+1,r);
mx[p]=max(mx[ls],mx[rs]);
}
void change(int p,int l,int r,int x){
if(vis[p])return;if(l==r)return vis[p]=1,val[p]=mx[p],void();
int mid=(l+r)>>1;
x<=mid?change(ls,l,mid,x):change(rs,mid+1,r,x);
val[p]=max(val[ls],val[rs]),vis[p]=vis[ls]&vis[rs];
}
void update(int p,int l,int r,int ql,int qr){
if(ql<=l&&qr>=r)return ++tag[p],void();
int mid=(l+r)>>1;
if(ql<=mid)update(ls,l,mid,ql,qr);
if(qr>mid)update(rs,mid+1,r,ql,qr);
}
void qmax(int p,int l,int r,int ql,int qr){
if(ql<=l&&qr>=r)return cmax(res,val[p]),void();
int mid=(l+r)>>1;
if(ql<=mid)qmax(ls,l,mid,ql,qr);
if(qr>mid)qmax(rs,mid+1,r,ql,qr);
}
int query(int p,int l,int r,int x,int t){
if(l==r)return t+tag[p];
int mid=(l+r)>>1;t+=tag[p];
return x<=mid?query(ls,l,mid,x,t):query(rs,mid+1,r,x,t);
}
void dfs1(int u){
sz[u]=1,dep[u]=dep[fa[u]]+1;
go(u)if(v!=fa[u]){
fa[v]=u,dfs1(v),sz[u]+=sz[v];
sz[v]>sz[son[u]]?son[u]=v:0;
}
}
void dfs2(int u,int t){
top[u]=t,dfn[u]=++cnt,rk[cnt]=a[u];
if(!son[u])return;
dfs2(son[u],t);
go(u)if(!top[v])dfs2(v,v);
}
void qwq(int u){
res=-1;
x=query(1,1,n,dfn[u],0);
x?res=a[u]:0;
while(u){
if(u!=top[u])qmax(1,1,n,dfn[top[u]],dfn[fa[u]]);
x=query(1,1,n,dfn[top[u]],0);
y=query(1,1,n,dfn[fa[top[u]]],0);
y>x?cmax(res,a[fa[top[u]]]):0;
u=fa[top[u]];
}
print(res);
}
void mdzz(int u){
if(ok[u])return;
ok[u]=1;
while(u){
update(1,1,n,dfn[top[u]],dfn[u]);
change(1,1,n,dfn[u]);
u=fa[top[u]];
}
}
int main(){
freopen("lca.in","r",stdin);
freopen("lca.out","w",stdout);
n=read(),m=read();
fp(i,1,n)a[i]=read();
fp(i,1,n-1)u=read(),v=read(),add(u,v),add(v,u);
dfs1(1),dfs2(1,1),build(1,1,n);
while(m--){
ch=getop(),u=read();
ch=='M'?mdzz(u):qwq(u);
}
return Ot(),0;
}
jzoj4918. 【GDOI2017模拟12.9】最近公共祖先 (树链剖分+线段树)的更多相关文章
- [BZOJ2164]采矿【模拟+树链剖分+线段树】
Online Judge:Bzoj2164 Label:模拟,树链剖分,线段树 题目描述 浩浩荡荡的cg大军发现了一座矿产资源极其丰富的城市,他们打算在这座城市实施新的采矿战略.这个城市可以看成一棵有 ...
- 马路 树链剖分/线段树/最近公共祖先(LCA)
题目 [问题描述] 小迟生活的城市是⼀棵树(树指的是⼀个含有 \(n\) 个节点以及 \(n-1\) 条边的⽆向连通图),节点编号从 \(1\) 到 \(n\),每条边拥有⼀个权值 \(value\) ...
- 树链剖分 (求LCA,第K祖先,轻重链剖分、长链剖分)
2020/4/30 15:55 树链剖分是一种十分实用的树的方法,用来处理LCA等祖先问题,以及对一棵树上的节点进行批量修改.权值和查询等有奇效. So, what is 树链剖分? 可以简单 ...
- BZOJ2040[2009国家集训队]拯救Protoss的故乡——模拟费用流+线段树+树链剖分
题目描述 在星历2012年,星灵英雄Zeratul预测到他所在的Aiur行星在M天后会发生持续性暴雨灾害,尤其是他们的首都.而Zeratul作为星灵族的英雄,当然是要尽自己最大的努力帮助星灵族渡过这场 ...
- 洛谷P3379 【模板】最近公共祖先(LCA)(树链剖分)
题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...
- jzoj5987. 【WC2019模拟2019.1.4】仙人掌毒题 (树链剖分+概率期望+容斥)
题面 题解 又一道全场切的题目我连题目都没看懂--细节真多-- 先考虑怎么维护仙人掌.在线可以用LCT,或者像我代码里先离线,并按时间求出一棵最小生成树(或者一个森林),然后树链剖分.如果一条边不是生 ...
- 【JZOJ4888】【NOIP2016提高A组集训第14场11.12】最近公共祖先
题目描述 YJC最近在学习树的有关知识.今天,他遇到了这么一个概念:最近公共祖先.对于有根树T的两个结点u.v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u.v的祖先且x的深度尽可能大. ...
- NOIP 模拟 $29\; \rm 最近公共祖先$
题解 \(by\;zj\varphi\) 首先考虑,如果将一个点修改成了黑点,那么它能够造成多少贡献. 它先会对自己的子树中的答案造成 \(w_x\) 的贡献. 考虑祖先时,它会对不包括自己的子树造成 ...
- 【GDOI2017模拟12.9】最近公共祖先
题目 分析 首先,将这些节点按dfs序建一棵线段树. 因为按dfs序,所以在同一子树上的节点会放在线段树相邻的位置. 发现,对于一个位置x,它的权值只会对以x为根的子树造成影响. 当修改x时,用w[x ...
随机推荐
- C++字符集问题终极分析(可解决乱码问题)
最近研究vc,windows的东西真是很傻瓜,啥都给你做好,有个好处就是开发方便了. 有个弊端就是完全按微软的一套进行,规则都是它定的,你得知道它的很多api, 开发出来的代码效率不高,不过却可以比较 ...
- 机器学习:模型泛化(L1、L2 和弹性网络)
一.岭回归和 LASSO 回归的推导过程 1)岭回归和LASSO回归都是解决模型训练过程中的过拟合问题 具体操作:在原始的损失函数后添加正则项,来尽量的减小模型学习到的 θ 的大小,使得模型的泛化能力 ...
- Python:格式化操作符(%)
原文作者:田小计划 原文出处:http://www.cnblogs.com/wilber2013/ (若转载,请标明原文出处) 在编写程序的过程中,经常需要进行格式化输出,每次用每次查.干脆就在这里整 ...
- spring学习十二 application/x-www-form-urlencoded还是application/json
application/x-www-form-urlencoded还是application/json get. POST 用哪种格式? 后台如何得到这些值? 如何用ajax 或者是 postman ...
- 数据库:sql 多表联合更新【转】
SQL Update多表联合更新的方法 (1) sqlite 多表更新方法 update t1 set col1=t2.col1 from table1 t1 inner join table2 t2 ...
- Android WebView 捕捉点击的URL中的信息
项目要求,在WebView中点击搜索关键字,加载其他Web页面时,需要在一个文本输入框中,实时显示关键字 事实上,这种点击,是WebView内的,并没有跳出这个WebView,Activity也没有经 ...
- Windows系统上release版本程序bug跟踪解决方案(1)-日志记录
使用场景: Win32程序在release模式下编译完成,发送给最终用户使用时,我们的程序有时候也会出现崩溃的情况,这个时候如果能快速定位崩溃原因或提供一些程序崩溃时的状态信息,对我们解决问题将会带来 ...
- 数据库访问优化漏斗法则- 四、减少数据库服务器CPU运算
数据库访问优化漏斗法则这个优化法则归纳为5个层次:1.减少数据访问次数(减少磁盘访问)2.返回更少数据(减少网络传输或磁盘访问)3.减少交互次数(减少网络传输)4.减少服务器CPU开销(减少CPU及内 ...
- oracle 之sys 、system区别
角色 1)最重要的区别,存储的数据的重要性不同sys--所有oracle的数据字典的基表和视图都存放在sys用户中,这些基表和视图对于oracle的运行是至关重要的,由数据库自己维护,任何用户都不能手 ...
- centos7虚拟机桥接上网(DHCP)
centos设置成自动获取ip地址方式(DHCP) 1.打开终端查看网卡信息 #ifconfigifcfg-enp0s3lovirbro 2.编辑文件#vim /etc/sysconfig/netwo ...