\(\mathcal{Description}\)

  Link. 做题原因:题目名。

  给定一个长度 \(n-1\) 的序列 \(\{a_2,a_3,\cdots,a_n\}\),其描述了一棵 \(n\) 个点的有根树—— \(1\) 为根节点,\(i~(i\in(1,n])\) 结点的父亲是 \(a_i~(a_i\in[1,i))\)。接下来有 \(q\) 次操作:

  1. 给定 \(l,r,x\),\(\forall i\in[l,r],~a_i\leftarrow \max\{a_i-x,1\}\);
  2. 给定 \(u,v\),求 \(u,v\) 在当前树上的 LCA。

  \(n,q\le10^5\)。

\(\mathcal{Solution}\)

  树是阿绫给的,操作是天依说的,所以题是一定会做的。

  首先明确一点:这是到题如其名的树题还是一道序列题。

  鉴于随便修改几下就可以把树拍得面目全非,前者可以叉掉,这就是道序列题。

  接着,思考 LCA 维护的形式,倍增太离谱了,考虑类似树剖维护 top 的方法——我们并不需要让 top 做到如树剖那样 \(\log\) 级别的优秀,这样才能应对灵活的修改。

  唠半天啦,这道题就是一道分块维护序列的题。


  首先根号分块,定义一个关键的 \(\operatorname{top}(u)\) 表示当前树上 \(u\) 的祖先中,不与 \(u\) 在同一块中的编号最大的结点,若不存在,则 \(\operatorname{top}(u)=1\)。发现美妙性质:跳 \(\operatorname{top}\) 链是 \(\mathcal O(\sqrt n)\) 的,收束前文提到的树剖思想;且暴力计算 \(\operatorname{top}(u)\) 是 \(\mathcal O(n)\) 的,非常方便。接了来只需要尝试维护这一信息。

  对于修改,散点暴力扫即可(注意一定是从左到右更新)。对于整块,我们似乎还是需要 \(\mathcal O(\sqrt n)\) 去重新更新 \(\operatorname{top}\)?

  答案是肯定的,但不完全——若一个整块被修改次数超过块的大小,则必然有 \(\operatorname{top}(u)=a_u\)。表明我们确实需要对于 \(\mathcal O(\sqrt n)\) 个块中的每一个,以 \(\mathcal O(\sqrt n)\) 的时间暴力处理其前 \(\operatorname O(\sqrt n)\) 次修改,不多不少,\(\mathcal O(n\sqrt n)\),此后直接对于整块记录减法标记即可。

  对于询问,亦类似树剖求 LCA:

  • 若 \(u,v\) 不属于同一块,\(u\leftarrow \operatorname{top}(u),v\leftarrow\operatorname{top}(v)\);
  • 否则若 \(\operatorname{top}(u)\not=\operatorname{top}(v)\),令 \(\operatorname{top}\) 较大的结点为其 \(\operatorname{top}\);
  • 否则,令较深结点为其父亲。

  跳 \(\operatorname{top}\) 至多 \(\mathcal O(\sqrt n)\) 下;跳父亲只会在同块时跳 \(\mathcal O(\sqrt n)\) 次(然后必然结束询问),所以单次查询是 \(\mathcal O(\sqrt n)\) 的。

  综上,复杂度 \(\mathcal O((n+q)\sqrt n)\),让天依满意啦~

\(\mathcal{Code}\)

/* Clearink */

#include <cmath>
#include <cstdio> #define rep( i, l, r ) for ( int i = l, repEnd##i = r; i <= repEnd##i; ++i )
#define per( i, r, l ) for ( int i = r, repEnd##i = l; i >= repEnd##i; --i ) inline int rint() {
int x = 0, f = 1, s = getchar();
for ( ; s < '0' || '9' < s; s = getchar() ) f = s == '-' ? -f : f;
for ( ; '0' <= s && s <= '9'; s = getchar() ) x = x * 10 + ( s ^ '0' );
return x * f;
} template<typename Tp>
inline void wint( Tp x ) {
if ( x < 0 ) putchar( '-' ), x = -x;
if ( 9 < x ) wint( x / 10 );
putchar( x % 10 ^ '0' );
} inline int imin( const int a, const int b ) { return a < b ? a : b; }
inline int imax( const int a, const int b ) { return a < b ? b : a; } const int MAXN = 1e5, MAXSN = 317;
int n, q, par[MAXN + 5];
int bsiz, bel[MAXN + 5], top[MAXN + 5], mcnt[MAXSN + 5], tag[MAXSN + 5]; #define utop( i ) ( top[i] = bel[par[i]] != bel[i] ? par[i] : top[par[i]] )
#define gpar( i ) ( pushdn( bel[i] ), par[i] )
#define gtop( i ) ( mcnt[bel[i]] >= bsiz ? pushdn( bel[i] ), par[i] : top[i] ) inline void init() {
bsiz = sqrt( 1. * n ), bel[1] = 1, bel[n + 1] = -1;
rep ( i, 2, n ) bel[i] = ( i - 1 ) / bsiz + 1, utop( i );
} inline void pushdn( const int i ) {
if ( !tag[i] ) return ;
int bl = ( i - 1 ) * bsiz + 1, br = imin( i * bsiz, n );
rep ( j, bl, br ) par[j] = imax( par[j] - tag[i], 1 );
// top[] is meaningless for this block.
tag[i] = 0;
} inline void modify( const int l, const int r, const int x ) {
pushdn( bel[l] );
for ( int i = l; bel[i] == bel[l]; ++i ) {
if ( i <= r ) par[i] = imax( par[i] - x, 1 );
utop( i );
}
if ( bel[l] == bel[r] ) return ;
rep ( i, bel[l] + 1, bel[r] - 1 ) {
if ( mcnt[i] >= bsiz ) { tag[i] += x; continue; }
++mcnt[i];
int bl = ( i - 1 ) * bsiz + 1, br = imin( i * bsiz, n );
rep ( j, bl, br ) par[j] = imax( par[j] - x, 1 ), utop( j );
}
pushdn( bel[r] );
for ( int i = ( bel[r] - 1 ) * bsiz + 1; bel[i] == bel[r]; ++i ) {
if ( i <= r ) par[i] = imax( par[i] - x, 1 );
utop( i );
}
} inline int query( int u, int v ) {
while ( u != v ) {
int tu = gtop( u ), tv = gtop( v );
if ( bel[u] != bel[v] ) bel[u] > bel[v] ? u = tu : v = tv;
else if ( tu != tv ) u = tu, v = tv;
else u > v ? u = gpar( u ) : v = gpar( v );
}
return u;
} int main() {
n = rint(), q = rint(), par[1] = 1;
rep ( i, 2, n ) par[i] = rint();
init();
for ( int op, u, v; q--; ) {
op = rint(), u = rint(), v = rint();
if ( op & 1 ) modify( u, v, rint() );
else wint( query( u, v ) ), putchar( '\n' );
}
return 0;
}

Solution -「CF 1491H」Yuezheng Ling and Dynamic Tree的更多相关文章

  1. Solution -「CF 1342E」Placing Rooks

    \(\mathcal{Description}\)   Link.   在一个 \(n\times n\) 的国际象棋棋盘上摆 \(n\) 个车,求满足: 所有格子都可以被攻击到. 恰好存在 \(k\ ...

  2. Solution -「CF 1622F」Quadratic Set

    \(\mathscr{Description}\)   Link.   求 \(S\subseteq\{1,2,\dots,n\}\),使得 \(\prod_{i\in S}i\) 是完全平方数,并最 ...

  3. Solution -「CF 923F」Public Service

    \(\mathscr{Description}\)   Link.   给定两棵含 \(n\) 个结点的树 \(T_1=(V_1,E_1),T_2=(V_2,E_2)\),求一个双射 \(\varph ...

  4. Solution -「CF 923E」Perpetual Subtraction

    \(\mathcal{Description}\)   Link.   有一个整数 \(x\in[0,n]\),初始时以 \(p_i\) 的概率取值 \(i\).进行 \(m\) 轮变换,每次均匀随机 ...

  5. Solution -「CF 1586F」Defender of Childhood Dreams

    \(\mathcal{Description}\)   Link.   定义有向图 \(G=(V,E)\),\(|V|=n\),\(\lang u,v\rang \in E \Leftrightarr ...

  6. Solution -「CF 1237E」Balanced Binary Search Trees

    \(\mathcal{Description}\)   Link.   定义棵点权为 \(1\sim n\) 的二叉搜索树 \(T\) 是 好树,当且仅当: 除去最深的所有叶子后,\(T\) 是满的: ...

  7. Solution -「CF 623E」Transforming Sequence

    题目 题意简述   link.   有一个 \(n\) 个元素的集合,你需要进行 \(m\) 次操作.每次操作选择集合的一个非空子集,要求该集合不是已选集合的并的子集.求操作的方案数,对 \(10^9 ...

  8. Solution -「CF 1023F」Mobile Phone Network

    \(\mathcal{Description}\)   Link.   有一个 \(n\) 个结点的图,并给定 \(m_1\) 条无向带权黑边,\(m_2\) 条无向无权白边.你需要为每条白边指定边权 ...

  9. Solution -「CF 599E」Sandy and Nuts

    \(\mathcal{Description}\)   Link.   指定一棵大小为 \(n\),以 \(1\) 为根的有根树的 \(m\) 对邻接关系与 \(q\) 组 \(\text{LCA}\ ...

随机推荐

  1. PPT2010制作翻牌动画

    原文: https://www.toutiao.com/i6492653280676545037/ 新建一张空白幻灯片 选择"插入"选项卡,"插入"功能组,&q ...

  2. 从如何使用到如何实现一个Promise

    前言 这篇文章我们一起来学习如何使用Promise,以及如何实现一个自己的Promise,讲解非常清楚,全程一步一步往后实现,附带详细注释与原理讲解. 如果你觉的这篇文章有帮助到你,️关注+点赞️鼓励 ...

  3. 【刷题-LeetCode】222. Count Complete Tree Nodes

    Count Complete Tree Nodes Given a complete binary tree, count the number of nodes. Note: Definition ...

  4. echart的x轴或y轴区间标签如何从大到小排列

    1.有时候我们做echart时,从后台接收返回回来的数据,没有按顺序排列,这里我遇到的是区间的值,看图 我这里是处理好了的,一开始,50-100这个区间在数组的最后一列,也就是在150-200后面的这 ...

  5. Servlet程序常见错误

    常见错误1:url-pattern中配置的路径没有以斜杠打头. 常见错误2:servlet-name配置的值不存在 常见错误3:servlet-class 标签的全类名配置错误

  6. ApacheCN - 关于我们

    1.简单介绍一下 ApacheCN? ApacheCN 是 2016 年 8 月份就开始搭建网站雏形, 2017 年 6 月份正式全职来做,是国内第一个有组织性.敢带人装逼.敢真的分享.并且敢戴绿帽的 ...

  7. 一些求和式的估算 & 杜教筛时间复杂度证明

    本文内容概要: \(A=\sum\limits_{i=1}^n\dfrac1{\sqrt i}=1+\dfrac1{\sqrt2}+\cdots+\dfrac1{\sqrt n}\) \(O(\sqr ...

  8. shiro和redis集成,前后端分离

    前言 框架:springboot+shiro+redis+vue 最近写前后端分离授权的对账平台系统,采取了shiro框架,若采用shiro默认的cookie进行授权验证时,一直存在由于跨域造成前端请 ...

  9. pageX的兼容性处理2

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. Linux常用命令,面试常考

    Linux常用命令 网络工具 查看监听端口的进程: lsof -i :8080 或者 netstat -tupln|grep 8080 复制 软连接创建 ln -s 源文件 目标文件