题解 \(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 最近公共祖先$的更多相关文章

  1. NOIP 模拟 $29\; \rm 完全背包问题$

    题解 \(by\;zj\varphi\) 一道 \(\rm dp\) 题. 现将所有种类从小到大排序,然后判断,若最小的已经大于了 \(\rm l\),那么直接就是一个裸的完全背包,因为选的总数量有限 ...

  2. NOIP 模拟 $29\; \rm 最长不下降子序列$

    题解 \(by\;zj\varphi\) 观察这个序列,发现模数很小,所以它的循环节很小. 那么可以直接在循环节上做最长上升子序列,但是循环节中的逆序对会对拼接后的答案造成影响. 没有必要找逆序对个数 ...

  3. noip模拟29[简单的板子题](虽然我不会)

    \(noip模拟29\;solutions\) 这次考试给我最大的伤害,让我意识到了差距 这场考试可以说是非常的简单,就是简单到,看两眼,打个表就有结果了 但是呢?我考得非常的完蛋,只有30pts 据 ...

  4. NOIp 图论算法专题总结 (1):最短路、最小生成树、最近公共祖先

    系列索引: NOIp 图论算法专题总结 (1) NOIp 图论算法专题总结 (2) NOIp 图论算法专题总结 (3) 最短路 Floyd 基本思路:枚举所有点与点的中点,如果从中点走最短,更新两点间 ...

  5. 8.3考试总结(NOIP模拟19)[最长不下降子序列·完全背包问题·最近公共祖先]

    一定要保护自己的梦想,即使牺牲一切. 前言 把人给考没了... 看出来 T1 是一个周期性的东西了,先是打了一个暴力,想着打完 T2 T3 暴力就回来打.. 然后,就看着 T2 上头了,后来发现是看错 ...

  6. hiho_1069_最近公共祖先3

    题目 给出一棵家族树,树上的节点可以由名字唯一标识.给出若干个查询,查询的内容为两个名字,结果为两个名字的最近公共祖先. 题目链接: 最近公共祖先 分析 在线的RMQ + LCA 算法,先用dfs将树 ...

  7. D5 LCA 最近公共祖先

    第一题: POJ 1330 Nearest Common Ancestors POJ 1330 这个题可不是以1为根节点,不看题就会一直wa呀: 加一个找根节点的措施: #include<alg ...

  8. 【IT笔试面试题整理】寻找二叉树两节点的最近的公共祖先

    [试题描述] 求二叉树中任意两个节点的最近公共祖先也称为LCA问题(Lowest Common Ancestor). 二叉查找树 如果该二叉树是二叉查找树,那么求解LCA十分简单. 基本思想为:从树根 ...

  9. NOIP模拟 1

    NOIP模拟1,到现在时间已经比较长了.. 那天是6.14,今天7.18了 //然鹅我看着最前边缺失的模拟1,还是终于忍不住把它补上,为了保持顺序2345重新发布了一遍.. #   用  户  名   ...

随机推荐

  1. WPF技巧:命中测试在视觉树中的使用

    我们有时候又需求从当前视觉树中找一些东西,比如鼠标按下的时候,看看鼠标下的元素都有什么.又比如某块区域下有哪些元素?某个坐标点下有哪些元素? 这些需求在使用 命中测试的时候,可以非常方便和快速的去找到 ...

  2. XSS一些总结

    XSS一些总结 除了script以外大多标签自动加载触发JS代码大多用的都是on事件,以下标签都可以用下面的方法去打Cookie以及url等 常见标签 <img><input> ...

  3. pxe+kickstart部署多个版本的Linux操作系统(下)---实践篇

        我们在企业运维环境中,难免会遇到使用多个Linux操作系统的情况,如果每天都需要安装不同版本的Linux系统的话,那么使用Kickstart只能安装一种版本的Linux系统的方法则显得有些捉襟 ...

  4. Python - bytes与字符串的相互转化

    decode和encode的区别和介绍 by.decode(encoding='UTF-8',errors='strict') str.encode(encoding='UTF-8',errors=' ...

  5. 选择适合入门的自动化测试框架TestNG 基于Java语言的入门选择之一

    对于测试工程师新手来说,最痛苦的莫过于入门,其实只要入门3个月左右,对于自动化测试,所有的测试工程师除了喜爱,就是更爱.自动化测试工作,是从根本上解放人性,不用重复去完成鼠标的点点点,例如以下测试常常 ...

  6. Qt5双缓冲机制与实例

    1. 双缓冲机制 所谓双缓冲机制,是指在绘制控件时,首先将要绘制的内容绘制在一个图片中,再将图片一次性地绘制到控件上. 在早期的Qt版本中,若直接在控件上进行绘制工作,则在控件重绘时会产生闪烁的现象, ...

  7. HDFS学习总结之安装

    HDFS linux安装总结(基于hadoop-2.6.0-cdh5.7.0 伪分部安装) 1.jdk安装 1) 直接下载jdk包放到安装目录即可(jdk-8u131-linux-x64.tar.gz ...

  8. height设置100%不起作用

    详细讲解了原因:http://www.webhek.com/post/css-100-percent-height.html

  9. PphpStorm常用操作整理

    本地修改记录:在项目名称上右键,点击Local History | Show History.你可以看到项目文件各个历史版本:Alt+Shift+C,可以看到项目最近的修改.这就是它的版本集成功能特性 ...

  10. Dijkstra和堆优化

    Dijkstra算法 由于我之前一直记的迪杰斯特拉的翻译导致我把dijkstra写成了dijstra--所以下文#define dijstra dijkstra 我以后叫她迪杰克斯歘! Dijskra ...