NOIP 模拟 $29\; \rm 最近公共祖先$
题解 \(by\;zj\varphi\)
首先考虑,如果将一个点修改成了黑点,那么它能够造成多少贡献。
它先会对自己的子树中的答案造成 \(w_x\) 的贡献。
考虑祖先时,它会对不包括自己的子树造成 \(w_fa\) 的贡献。
那么思路很显然,直接暴力向上更新,若更新到一个祖先,它已经被更新过了,那么更新完它之后直接退出就行,因为再向上,一定已经被更新过了。
实现的过程用在 \(\rm dfs\) 序上建线段树即可。
这样,每个点最多被更新一次,在询问时,最多重复更新一个点,所以总复杂度为 \(\mathcal O\rm((n+m)logn)\)
Code
#include<bits/stdc++.h>
#define ri register signed
#define p(i) ++i
namespace IO{
char buf[1<<21],*p1=buf,*p2=buf;
#define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?(-1):*p1++
struct nanfeng_stream{
template<typename T>inline nanfeng_stream &operator>>(T &x) {
ri f=1;x=0;register char ch=getchar();
while(!isdigit(ch)) {if (ch=='-') x=-1;ch=getchar();}
while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x=f?x:-x,*this;
}
}cin;
}
using IO::cin;
namespace nanfeng{
#define FI FILE *IN
#define FO FILE *OUT
template<typename T>inline T cmax(T x,T y) {return x>y?x:y;}
template<typename T>inline T cmin(T x,T y) {return x>y?y:x;}
static const int N=1e5+7;
int first[N],w[N],ld[N],rd[N],B[N],fa[N],t=1,n,m,tot,ol,nm;
char s[N];
struct edge{int v,nxt;}e[N<<1];
inline void add(int u,int v) {
e[t].v=v,e[t].nxt=first[u],first[u]=t++;
e[t].v=u,e[t].nxt=first[v],first[v]=t++;
}
void dfs(int x,int f) {
ld[x]=p(tot);
for (ri i(first[x]),v;i;i=e[i].nxt) {
if ((v=e[i].v)==f) continue;
fa[v]=x;
dfs(v,x);
}
rd[x]=tot;
}
struct Seg{
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
#define up(x) T[x].mx=cmax(T[ls(x)].mx,T[rs(x)].mx)
struct segmenttree{int mx,lz;}T[N<<2];
inline void down(int x) {
if (!T[x].lz) return;
T[ls(x)].mx=cmax(T[ls(x)].mx,T[x].lz);
T[rs(x)].mx=cmax(T[rs(x)].mx,T[x].lz);
T[ls(x)].lz=cmax(T[ls(x)].lz,T[x].lz);
T[rs(x)].lz=cmax(T[rs(x)].lz,T[x].lz);
T[x].lz=0;
}
int query(int x,int p,int l,int r) {
if (l==r) return T[x].mx;
int mid(l+r>>1);
down(x);
if (p<=mid) return query(ls(x),p,l,mid);
else return query(rs(x),p,mid+1,r);
}
void update(int x,int k,int l,int r,int lt,int rt) {
if (l<=lt&&rt<=r) {
T[x].mx=cmax(T[x].mx,k);
return (void)(T[x].lz=cmax(T[x].lz,k));
}
int mid(lt+rt>>1);
down(x);
if (l<=mid) update(ls(x),k,l,r,lt,mid);
if (r>mid) update(rs(x),k,l,r,mid+1,rt);
up(x);
}
}T;
inline void update(int x) {
ri nw=x,ns=x;
T.update(1,w[x],ld[nw],rd[nw],1,n);
B[nw]=1;
nw=fa[nw];
while(nw) {
for (ri i(first[nw]),v;i;i=e[i].nxt) {
if ((v=e[i].v)==ns||v==fa[nw]) continue;
T.update(1,w[nw],ld[v],rd[v],1,n);
}
if (B[nw]) return;
T.update(1,w[nw],ld[nw],ld[nw],1,n);
B[nw]=1;
ns=fa[ns],nw=fa[nw];
}
}
inline int main() {
//FI=freopen("nanfeng.in","r",stdin);
//FO=freopen("nanfeng.out","w",stdout);
cin >> n >> m;
for (ri i(1);i<=n;p(i)) cin >> w[i];
for (ri i(1),u,v;i<n;p(i)) cin >> u >> v,add(u,v);
dfs(1,0);
for (ri i(1),v;i<=m;p(i)) {
scanf("%s",s+1);
cin >> v;
if (s[1]=='Q') {
if (!nm) puts("-1");
else printf("%d\n",T.query(1,ld[v],1,n));
} else p(nm),update(v);
}
return 0;
}
}
int main() {return nanfeng::main();}
NOIP 模拟 $29\; \rm 最近公共祖先$的更多相关文章
- NOIP 模拟 $29\; \rm 完全背包问题$
题解 \(by\;zj\varphi\) 一道 \(\rm dp\) 题. 现将所有种类从小到大排序,然后判断,若最小的已经大于了 \(\rm l\),那么直接就是一个裸的完全背包,因为选的总数量有限 ...
- NOIP 模拟 $29\; \rm 最长不下降子序列$
题解 \(by\;zj\varphi\) 观察这个序列,发现模数很小,所以它的循环节很小. 那么可以直接在循环节上做最长上升子序列,但是循环节中的逆序对会对拼接后的答案造成影响. 没有必要找逆序对个数 ...
- noip模拟29[简单的板子题](虽然我不会)
\(noip模拟29\;solutions\) 这次考试给我最大的伤害,让我意识到了差距 这场考试可以说是非常的简单,就是简单到,看两眼,打个表就有结果了 但是呢?我考得非常的完蛋,只有30pts 据 ...
- NOIp 图论算法专题总结 (1):最短路、最小生成树、最近公共祖先
系列索引: NOIp 图论算法专题总结 (1) NOIp 图论算法专题总结 (2) NOIp 图论算法专题总结 (3) 最短路 Floyd 基本思路:枚举所有点与点的中点,如果从中点走最短,更新两点间 ...
- 8.3考试总结(NOIP模拟19)[最长不下降子序列·完全背包问题·最近公共祖先]
一定要保护自己的梦想,即使牺牲一切. 前言 把人给考没了... 看出来 T1 是一个周期性的东西了,先是打了一个暴力,想着打完 T2 T3 暴力就回来打.. 然后,就看着 T2 上头了,后来发现是看错 ...
- hiho_1069_最近公共祖先3
题目 给出一棵家族树,树上的节点可以由名字唯一标识.给出若干个查询,查询的内容为两个名字,结果为两个名字的最近公共祖先. 题目链接: 最近公共祖先 分析 在线的RMQ + LCA 算法,先用dfs将树 ...
- D5 LCA 最近公共祖先
第一题: POJ 1330 Nearest Common Ancestors POJ 1330 这个题可不是以1为根节点,不看题就会一直wa呀: 加一个找根节点的措施: #include<alg ...
- 【IT笔试面试题整理】寻找二叉树两节点的最近的公共祖先
[试题描述] 求二叉树中任意两个节点的最近公共祖先也称为LCA问题(Lowest Common Ancestor). 二叉查找树 如果该二叉树是二叉查找树,那么求解LCA十分简单. 基本思想为:从树根 ...
- NOIP模拟 1
NOIP模拟1,到现在时间已经比较长了.. 那天是6.14,今天7.18了 //然鹅我看着最前边缺失的模拟1,还是终于忍不住把它补上,为了保持顺序2345重新发布了一遍.. # 用 户 名 ...
随机推荐
- Luogu P4313 文理分科
link 最小割 双倍经验 这道题运用了最小割最常用的一种用法:集合划分. 因为源汇最小割即就是将源汇划分到不同的集合,那么最简单的应用就是最小代价划分集合了. 本题中,题意是将 \(n\cdot m ...
- c语言字符串占据字节数
# include <stdio.h> //字符串占据的字节数 /* 不能将一个字符串常量赋给一个字符变量 为什么不能将一个字符串常量赋给一个字符变量?可以从两个方面作出解释: 前面讲过, ...
- [刘阳Java]_MyBatis_其他方式来实现多表查询的操作_第9讲
MyBatis其他方式来实现多表查询的操作 利用Java中的集合框架(List,Map) 其中List存储多个查询返回的记录 Map查询返回字段,同时记录表中一条数据 <?xml version ...
- 【算法学习笔记】概率与期望DP
本文学习自 Sengxian 学长的博客 之前也在CF上写了一些概率DP的题并做过总结 建议阅读完本文再去接着阅读这篇文章:Here 前言 单纯只用到概率的题并不是很多,从现有的 OI/ACM 比赛中 ...
- HDFS学习总结之架构
一.hdfs介绍 官网说明 Hadoop Distributed File System (HDFS): A distributed file system that provides high-th ...
- 详述 IntelliJ IDEA 远程调试 Tomcat 的方法
首先,配置remote: 如上图所示,点击Edit Configurations,进入如下界面: 如上图所示,我们进入了Run/Debug Configurations界面,然后点击左上角的+,选择R ...
- 微信小程序云开发-云函数-初始化云函数环境
一.新建云函数文件夹 新建的云函数文件夹,命名为cloud,该文件夹一定要与pages文件夹同级.此时该文件夹的前面没有云朵的标识. 二.配置project.config.json文件 在proje ...
- 【spring源码系列】之【Bean的循环依赖】
希望之光永远向着目标清晰的人敞开. 1. 循环依赖概述 循环依赖通俗讲就是循环引用,指两个或两个以上对象的bean相互引用对方,A依赖于B,B依赖于A,最终形成一个闭环. Spring循环依赖的场景有 ...
- js中变量提升和函数提升
变量提升和函数提升的总结 我们在学习JavaScript时,会遇到变量提升和函数提升的问题,为了理清这个问题,现做总结如下,希望对初学者能有所帮助 我们都知道 var 声明的变量有变量提升,而 let ...
- 论文笔记:(2017NIPS)DeepSets
目录 摘要 一.引言 二.置换不变性和等变性 2.1 问题定义 2.2 结构 2.3 相关结果 三.Deep Sets 3.1 架构 3.2 其他相关工作 四.应用和实验结果 4.1 设置输入标量响应 ...