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重新发布了一遍.. # 用 户 名 ...
随机推荐
- ESP32-OTA升级
基于ESP-IDF4.1 1 #include <string.h> 2 #include "freertos/FreeRTOS.h" 3 #include " ...
- Python获取list中指定元素的索引
在平时开发过程中,经常遇到需要在数据中获取特定的元素的信息,如到达目的地最近的车站,橱窗里面最贵的物品等等.怎么办?看下面 方法一: 利用数组自身的特性 list.index(target), 其中a ...
- XDFZOI 月赛 201905 Sliver
组题人自己组完过后,才发现自己还是太弱了... T1 简单模拟. 按照游戏规则直接模拟显然是不明智的,所以我们可以像石头剪刀布一样,将判断改变为检验. 同时,我们发现,一共只有48种牌,所以我们可以直 ...
- Django基础008--model多对多
1.多对多表结构设计 class Student(models.Model): name = models.CharField(verbose_name='学生名字',max_length=100) ...
- clickhouse分布式集群
一.环境准备: 主机 系统 应用 ip ckh-01 centos 8 jdk,zookeeper,clickhouse 192.168.205.190 ckh-02 centos 8 jdk,zoo ...
- File类与常用IO流第八章——缓冲流
第八章.缓冲流 缓冲流概述 缓冲流,也叫高效流,是对4个基本的FileXxx流的增强.按照数据类型分为4类: 输入缓冲流 输出缓冲流 字节缓冲流 BufferedInputStream Buffe ...
- 浅析vue-cli脚手架命令的执行过程
上一篇文章,已经大致了解脚手架是什么以及脚手架是如何工作的.接下来,稍微深入一下脚手架的工作过程(以vue-cli为例).首先抛出3个问题: 1.明明全局安装的是@vue/cli,最后执行的命令却是v ...
- 初探SpringRetry机制
重试是在网络通讯中非常重要的概念,尤其是在微服务体系内重试显得格外重要.常见的场景是当遇到网络抖动造成的请求失败时,可以按照业务的补偿需求来制定重试策略.Spring框架提供了SpringRetry能 ...
- [NOI 2021] 轻重边 题解
提供一种和不太一样的树剖解法(一下考场就会做了qwq),尽量详细讲解. 思路 设重边为黑色,轻边为白色. 首先,先将边的染色转化为点的染色(即将 \(u\) 节点连向父节点的边的颜色转化为 \(u\) ...
- (opencv09)cv2.getStructuringElement()构造卷积核
(opencv09)cv2.getStructuringElement()构造卷积核 rectkernel = cv2.getStructuringElement(shape, ksize, anch ...