将其按照区间分块(即$[(i-1)K+1,iK]$作为一个块),并定义$f_{x}$表示$x$的祖先中编号最小且与$x$在同一个块内的节点,$f_{x}$可以通过$f_{a_{x}}$转移,即$f_{x}=\begin{cases}f_{a_{x}}\ \ \ (x与a_{x}在一个块中)\\x\ \ \ \ \ \ (x与a_{x}不在一个块中)\end{cases}$

(特别的,若$x$在第一个块中则$f_{x}=1$)

通过$f_{x}$,类似于树剖的方式,即若两者$f_{x}$不同则移动$f_{x}$较大的(移动到$f_{x}$),直至相同再用同样的方式爬$a_{x}$,复杂度显然是$o(q\sqrt{n})$的

接下来是如何维护$f_{x}$,即如何支持修改:

对于边角的两个块,显然是可以暴力维护的,对于整块修改,显然当一个块被修改$\sqrt{n}$次后一定有$f_{x}=x$,因此至多$o(n)$次暴力,复杂度也是$o(n\sqrt{n})$

最终总复杂度即为$o((n+q)\sqrt{n})$

 1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 100005
4 int n,m,K,p,x,y,z,a[N],bl[N],st[N],ed[N],f[N];
5 long long tag[N];
6 int get(int k){
7 return max(a[k]-tag[bl[k]],1LL);
8 }
9 void calc(int x,int y){
10 for(int i=x;i<=y;i++)
11 if (bl[i]==1)f[i]=1;
12 else{
13 int x=get(i);
14 if (bl[x]!=bl[i])f[i]=i;
15 else f[i]=f[x];
16 }
17 }
18 int main(){
19 scanf("%d%d",&n,&m);
20 for(int i=2;i<=n;i++)scanf("%d",&a[i]);
21 K=(int)sqrt(n);
22 for(int i=1;i<=n;i++)bl[i]=(i-1)/K+1;
23 for(int i=1;i<=bl[n];i++){
24 st[i]=(i-1)*K+1;
25 ed[i]=min(i*K,n);
26 calc(st[i],ed[i]);
27 }
28 calc(1,n);
29 for(int i=1;i<=m;i++){
30 scanf("%d%d%d",&p,&x,&y);
31 if (p==1){
32 scanf("%d",&z);
33 if (bl[x]==bl[y]){
34 for(int j=x;j<=y;j++)a[j]=max(a[j]-z,1);
35 calc(st[bl[x]],ed[bl[x]]);
36 }
37 else{
38 for(int j=x;j<=ed[bl[x]];j++)a[j]=max(a[j]-z,1);
39 calc(st[bl[x]],ed[bl[x]]);
40 for(int j=st[bl[y]];j<=y;j++)a[j]=max(a[j]-z,1);
41 calc(st[bl[y]],ed[bl[y]]);
42 for(int j=bl[x]+1;j<=bl[y]-1;j++){
43 tag[j]+=z;
44 if (tag[j]-z<=K)calc(st[j],ed[j]);
45 }
46 }
47 }
48 else{
49 while (f[x]!=f[y]){
50 if (f[x]>f[y])swap(x,y);
51 y=get(f[y]);
52 }
53 if (x==y){
54 printf("%d\n",x);
55 continue;
56 }
57 while (get(x)!=get(y)){
58 if (get(x)>get(y))swap(x,y);
59 y=get(y);
60 }
61 if (x==y)printf("%d\n",x);
62 else printf("%d\n",get(x));
63 }
64 }
65 }

最新文章

  1. 《ES6基础教程》之 map、forEach、filter indexOf 用法
  2. js事件浅析
  3. AngularJS入门教程1--配置环境
  4. 安装使用RESTful 框架SLIM方法
  5. Eyeshot Ultimate 学习笔记(1)
  6. WIN2003+IIS6+FastCGI+PHP5.4.30的安装配置
  7. Unity 使用 陀螺仪 实现 《王者荣耀》 登入界面 背景动态效果
  8. php函数var_dump() 、print_r()、echo()
  9. linux 下检查java jar包 程序是否正常 shell
  10. 第二篇——Struts2的Action搜索顺序
  11. Jmeter(三十二)_搭建本地接口自动化环境
  12. Eclipse 下载安装
  13. Scala类的构造器与访问器
  14. [mobile]监听手机mobile上面软键盘的回车[enter]事件
  15. js中的json的小例子
  16. 杂货&amp;&amp;心跳
  17. Mysql 於lampp xampp LinuxUbuntu下的配置
  18. Lora通信解决方案对比
  19. 机器学习基础 --- pandas的基本使用
  20. ibatis 调用存储过程

热门文章

  1. Sentry 监控 - Snuba 数据中台架构(Query Processing 简介)
  2. visualbox安装ubuntu18过程中不能输入name,password,密码,姓名问题的解决办法+一些基本操作
  3. bzoj2037 Sue的小球(区间dp,考虑到对未来的贡献)
  4. js 面向对象 动态添加标签
  5. HCNP Routing&amp;Switching之BGP防环机制和路由聚合
  6. Redis:学习笔记-01
  7. MySQL:基础语法-1
  8. 理解ASP.NET Core - 路由(Routing)
  9. UltraSoft - Alpha - 发布声明
  10. Spring源码解读(一):Spring的背景起源及框架整体介绍