CF1491H Yuezheng Ling and Dynamic Tree

  • description
  • solution
  • code

description

题目链接

solution

非常清新的小分块题了

前提:将序列分成n\sqrt{n}n​块,每块有n\sqrt{n}n​个数,记第iii个块的左右边界为Li,RiL_i,R_iLi​,Ri​,记第iii个数所在块为blockiblock_iblocki​

定义topitop_itopi​:节点iii的祖先中,与iii不在同一个块的最大编号点

【这个真的很妙,可以说是这道题的解法考察点了】

问题是如何在al,ra_{l,r}al,r​更新时,对某个块xxx内的被覆盖节点i∈[l,r]i\in[l,r]i∈[l,r]的topitop_itopi​进行更新??

  • 如果更新后的ai<Lxa_i<L_xai​<Lx​,则aia_iai​成为新的满足toptoptop定义的最大编号点【iii的祖先都已经全变成了aia_iai​的祖先,再加个aia_iai​本身】,topi=aitop_i=a_itopi​=ai​
  • 如果更新后的aia_iai​仍然属于块xxx内,则直接链接过去,topi=topaitop_i=top_{a_i}topi​=topai​​

明白了如何维护块内信息,接下来就是对不同块进行操作了

首先考虑修改操作

  • 散块(只覆盖了块内部分点):直接暴力修改点的aia_iai​值,然后暴力重构,单次操作时间复杂度O(n)O(\sqrt{n})O(n​)

  • 整块:懒标记tagitag_itagi​表示点iii的aia_iai​还没减多少【比真实的aia_iai​多了tagitag_itagi​,未真实操作修改】,但这个时候块内某些点的topitop_itopi​可能已经发生了变化,没有实时更新就会影响后面的查询操作,而每次暴力修改又需要整个块的遍历,多个整块几乎就是O(O(O(修改区间长度)))的,无法保证时间复杂度

    实际上,发现对于每个块,经过n\sqrt{n}n​次整块修改操作后,aia_iai​都至少会变为ai−na_i-\sqrt{n}ai​−n​,一定在当前块前面的块

    因此,我们可以维护每个块被修改的次数cntxcnt_xcntx​当cntx>ncnt_x>\sqrt{n}cntx​>n​,就不再暴力修改整块,而是直接整块的区间减法,这个时候的aia_iai​一定是其的topitop_itopi​,否则就暴力修改

    每个块最多修改n\sqrt{n}n​次,每次需要O(n)O(\sqrt{n})O(n​)遍历修改,一共有n\sqrt{n}n​个块,总时间复杂度是O(nn)O(n\sqrt{n})O(nn​)的

接着考虑询问操作

找lca\text{lca}lca肯定是倍增暴力啦!这里直接使用暴力爬山法

考虑询问u,vu,vu,v两个点的lcalcalca

  • 若blocku≠blockvblock_u\neq block_vblocku​​=blockv​,则选择对应blockblockblock编号较大的点,跳到其toptoptop点

  • 若blocku=blockvblock_u=block_vblocku​=blockv​且topu≠topvtop_u\neq top_vtopu​​=topv​,则两个节点一起跳对应的toptoptop点

  • 若blocku=blockvblock_u=block_vblocku​=blockv​且topu=topvtop_u=top_vtopu​=topv​,则一直让节点编号大的点跳父亲aaa,直到两点相同为止

    【注意在跳的时候,一定要减去所在块的tagxtag_xtagx​标记,才能得到真正的top/atop/atop/a】

一个点跳toptoptop的次数最多为nn=n\frac{n}{\sqrt{n}}=\sqrt{n}n​n​=n​次,跳完toptoptop就是在一个块里面的跳aaa,最多也是n\sqrt{n}n​次,所以单次询问时间复杂度为O(n)O(\sqrt{n})O(n​)

本题最终的时间复杂度为O((n+q)n)O((n+q)\sqrt{n})O((n+q)n​)

code

#include <cmath>
#include <cstdio>
#include <iostream>
using namespace std;
#define maxn 100005
#define maxB 320
int n, Q, B, B_cnt;
int a[maxn], block[maxn], L[maxB], R[maxB], cnt[maxB], top[maxn], tag[maxB];void pushup( int x ) {for( int i = L[x];i <= R[x];i ++ ) a[i] = max( 1, a[i] - tag[x] );tag[x] = 0;for( int i = L[x];i <= R[x];i ++ ) {if( a[i] < L[x] ) top[i] = a[i];else top[i] = top[a[i]];}
}void modify( int l, int r, int x ) {if( block[l] == block[r] ) {for( int i = l;i <= r;i ++ ) a[i] = max( 1, a[i] - x );pushup( block[l] );}else {for( int i = l;i <= R[block[l]];i ++ ) a[i] = max( 1, a[i] - x ); pushup( block[l] );for( int i = L[block[r]];i <= r;i ++ ) a[i] = max( 1, a[i] - x ); pushup( block[r] );for( int i = block[l] + 1;i < block[r];i ++ ) {cnt[i] ++, tag[i] = min( n, tag[i] + x );if( cnt[i] <= B ) pushup( i );}}
}int query_top( int i ) { return max( 1, top[i] - tag[block[i]] ); }int query_a( int i ) { return max( 1, a[i] - tag[block[i]] ); }int lca( int x, int y ) {while( 1 ) {if( block[x] < block[y] ) swap( x, y );if( block[x] ^ block[y] ) x = query_top( x );else {if( top[x] ^ top[y] ) x = query_top( x ), y = query_top( y );else break;}}while( x ^ y ) {if( x < y ) swap( x, y );x = query_a( x );}return x;
}int main() {scanf( "%d %d", &n, &Q );B = sqrt( n ), B_cnt = ( n - 1 ) / B + 1;for( int i = 2;i <= n;i ++ ) {scanf( "%d", &a[i] );block[i] = ( i - 1 ) / B + 1;}for( int i = 1;i <= block[n];i ++ ) L[i] = ( i - 1 ) * B + 1, R[i] = min( n, i * B ), pushup( i );for( int i = 1, opt, l, r, x;i <= Q;i ++ ) {scanf( "%d %d %d", &opt, &l, &r );if( opt & 1 ) scanf( "%d", &x ), modify( l, r, x );else printf( "%d\n", lca( l, r ) );}return 0;
}

CF1491H Yuezheng Ling and Dynamic Tree(分块)相关推荐

  1. 文献记录(part6)--Dynamic Tree Cut in-depth description, tests and applications

    学习笔记,仅供参考,有错必究 文章目录 Dynamic Tree Cut: in-depth description, tests and applications 摘要 Dynamic Tree C ...

  2. 论文Spatial-Temporal Transformer for Dynamic Scene Graph Generation

    最近由于要做SGG方向,恰巧之前保存过这篇论文 2107.12309.pdf (arxiv.org)https://arxiv.org/pdf/2107.12309.pdf 代码地址: GitHub ...

  3. 对LCA、树上倍增、树链剖分(重链剖分长链剖分)和LCT(Link-Cut Tree)的学习

    LCA what is LCA & what can LCA do LCA(Lowest Common Ancestors),即最近公共祖先 在一棵树上,两个节点的深度最浅的公共祖先就是 L ...

  4. 【CVPR2019_论文汇总】(按方向划分,0401 更新中)

    转载链接:http://bbs.cvmart.net/topics/302/cvpr2019paper 作为计算机视觉领域三大顶会之一,CVPR2019(2019.6.16-6.19在美国洛杉矶举办) ...

  5. CVPR 2019 论文汇总(按方向划分,0409 更新中)[转载]

    转载链接:http://bbs.cvmart.net/topics/302/cvpr2019paper 作为计算机视觉领域三大顶会之一,CVPR2019(2019.6.16-6.19在美国洛杉矶举办) ...

  6. WGCNA分析,简单全面的最新教程

    本文应该是第二全的WGCNA分析教程,参考了最新的文档.第一全的还在路上,会出现于生信宝典和宏基因组公众号组织的二代三代转录组测序分析实战班上,欢迎点击链接了解更多. WGCNA基本概念 加权基因共表 ...

  7. 一训练就显存爆炸?Facebook 推出 8 比特优化器,两行代码拯救你的显存

    自从人们发现越大的模型性能越好后,神经网络模型的参数量就在越来越大的道路上一去不复返了.从XX-large到GPT3,再到5300亿参数的Megatron Turing-NLG,深度学习越来越像是只有 ...

  8. 2019年, SGG论文汇总

    目录 CVPR2019:VCTree ICCV2019:CMAT CVPR2019:Knowledge-Embedded Routing Network CVPR2019:VCTree 题目 Lear ...

  9. CVPR 2019 | 腾讯AI Lab解读六大前沿方向及33篇入选论文

    导语:本文将分组介绍计算机视觉顶级会议 CVPR 中腾讯 AI Lab 的重点研究方向和入选论文. 计算机视觉顶级会议 CVPR 2019 将于 6 月 15 日– 6 月 21 日在加利福尼亚州长滩 ...

最新文章

  1. TDSQL在微众银行的大规模实践之路
  2. 特别策划:视频会议协作平台的机会与技术挑战
  3. 计算机的外部设备 硬盘,外部设备采用SMB协议想共享电脑硬盘下的文件
  4. 实验三:跟踪分析Linux内核启动过程
  5. mysql publishedtime_MySQL数据库中的Date,DateTime,TimeStamp和Time类型
  6. C语言入门篇(二)指针的介绍和运用
  7. 【GCN+AE代码逐行学习】参考资料记录
  8. autojs识别数字ocr
  9. 从信号与系统,数字信号处理的角度看目前手头研发的蓝牙耳机
  10. 微型计算机是以微处理器为基础,在计算机中以微处理器为核心组成的微型计算机属于第几代计算机...
  11. 南大小百合 计算机,是我从南大小百合里搜集的。已经编辑过了
  12. super-csv文档的部分翻译及基本使用
  13. 中了exe病毒文件夹变exe应用程序解决办法
  14. postgresql - SQL查询某一天内的记录
  15. 【c#】获取DGV单元格对象方法dgv按钮列的使用介绍
  16. pytorch 梯度计算相关内容总结
  17. 服务器gosht引导盘,带RAID服务器能GHOST备份吗?
  18. 12、【股票策略】使用backtrader回测升级版的狗股策略-基于股息率和市净率两个因子
  19. 基于单片机的交通灯信号控制器设计
  20. Linux系统下的分区管理

热门文章

  1. 全球100款大数据工具汇总(前50款)
  2. linux ntfs 速度慢,将U盘磁盘格式改成NTFS解决u盘复制速度慢问题
  3. java guava json文件_Json解析文件位置的问题
  4. redis 查询缓存_Redis缓存总结:淘汰机制、缓存雪崩、数据不一致....
  5. python +appium实现原理_python_appium使用原理
  6. get+php+mysql_Apache+PHP+MySql 的安装及配置
  7. 理请求时出现未知错误.服务器返回的状态码为: 500,react-native
  8. linux进程的高级管理,Linux高级程序设计(第2版) PDF扫描版[94MB]
  9. oracle数据缓冲区作用,Oracle内存结构(02)--缓冲区
  10. js-cookie 无法设置cookie_php操作 cookie