答案即区间$[l,r]$的笛卡尔树上,左右子树有一个为空的点到根路径和(定义此为的该点答案)的max,

对求区间笛卡尔树复杂度为$o(n)$,无法通过,因此在全局笛卡尔树中考虑此问题

设$k$为$l$和$r$的lca,那么$i$的答案就是$i$到$k$路径中在$[l,r]$中的部分的和

对于$i$所在子树分类,即将$[l,r]$分为$[l,k)$和$(k,r]$两部分(分别求max),以下以左半部分为例:

考虑$i$到$k$的链,由于$i$在$k$左子树中,因此这条链也时刻在$k$左子树中,即其一定在$k$也就是$r$的左边,因此只需要考虑这个位置大于等于$l$

进一步的,再求$l$和$i$的lca(记为$j$),由于是lca且$l\le i$,因此$l$一定在$j$的左子树中,$i$在$j$的右子树中,因此$i$到$j$的这一部分一定都在$l$的右边,换言之可以枚举lca,直接对右子树内所有点深度取max

还要考虑$j$到$k$的部分,即求这一部分中在$l$右边的数之和,这件事是与$l$无关而仅和$j$本身有关,凡是这条链上其儿子是其右儿子的都不能被计算

(因为这就说明了$k$在其右子树,$l$又在$k$子树内,即$l$在其的右边,反之就说明$l$在左边)

根据上面的性质,具体过程如下——

预处理出以下三个数组:$s_{1}[k]$表示$k$到根路径中所有点的和,$s_{2}[k]$表示其中所有儿子是左儿子的点之和(特别的,$k$都计算入内),$mx[k]$表示$k$子树中满足左右子树有一个为空的点的$s_{1}[k]$的最大值

考虑询问$[l,k)$,暴力枚举$j$,则对于给定的$j$,其对答案的贡献为$mx[rs[j]]-s_{1}[j]+s_{2}[j]-s_{2}[k]+w[k]$(注意$j$一定在$l$的右边,否则不可能是$l$和$i$的lca),贡献是取max

离线,将询问挂在$l$上,然后遍历笛卡尔树,对于点$k$,将$mx[rs[k]]-s_{1}[k]+s_{2}[k]$记在以$k$的深度为下标的线段树上,然后搜索左子树,当搜索右子树时撤销此记录

对于询问,求出$k$(指询问的顶点)的深度+1到$l$的深度这段区间在线段树上的最大值即可(由于$l$的右子树也是可以的,因此先修改再询问)

(右半部分类似,即只考虑其儿子是右儿子的点)

注意要开long long,时间复杂度为$o(n\log_{2}n)$,可以通过

 1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 500005
4 #define ll long long
5 #define L (k<<1)
6 #define R (L+1)
7 #define mid (l+r>>1)
8 vector<pair<int,int> >vl[N],vr[N];
9 int n,q,x,y,a[N],w[N],st[N],ls[N],rs[N],s[N],f[N][21];
10 ll s1[N],s2[N],s3[N],mx[N],ans[N],tr[N<<2];
11 int lca(int x,int y){
12 if (s[x]<s[y])swap(x,y);
13 for(int i=20;i>=0;i--)
14 if (s[f[x][i]]>=s[y])x=f[x][i];
15 if (x==y)return x;
16 for(int i=20;i>=0;i--)
17 if (f[x][i]!=f[y][i]){
18 x=f[x][i];
19 y=f[y][i];
20 }
21 return f[x][0];
22 }
23 void dfs(int k,int fa){
24 if (!k)return;
25 s[k]=s[fa]+1;
26 s1[k]=s1[fa]+w[k];
27 s2[k]+=s2[fa]+w[k];
28 s3[k]+=s3[fa]+w[k];
29 f[k][0]=fa;
30 for(int i=1;i<=20;i++)f[k][i]=f[f[k][i-1]][i-1];
31 if (ls[k])s3[ls[k]]=-w[k];
32 dfs(ls[k],k);
33 if (rs[k])s2[rs[k]]=-w[k];
34 dfs(rs[k],k);
35 mx[k]=max(mx[ls[k]],mx[rs[k]]);
36 if ((!ls[k])||(!rs[k]))mx[k]=max(mx[k],s1[k]);
37 }
38 void update(int k,int l,int r,int x,ll y){
39 if (l==r){
40 tr[k]=y;
41 return;
42 }
43 if (x<=mid)update(L,l,mid,x,y);
44 else update(R,mid+1,r,x,y);
45 tr[k]=max(tr[L],tr[R]);
46 }
47 ll query(int k,int l,int r,int x,int y){
48 if ((l>y)||(x>r))return -1e15;
49 if ((x<=l)&&(r<=y))return tr[k];
50 return max(query(L,l,mid,x,y),query(R,mid+1,r,x,y));
51 }
52 void calc_l(int k){
53 if (!k)return;
54 if (!rs[k])update(1,1,n,s[k],s2[k]);
55 else update(1,1,n,s[k],mx[rs[k]]-s1[k]+s2[k]);
56 for(int i=0;i<vl[k].size();i++){
57 x=vl[k][i].first,y=vl[k][i].second;
58 ans[y]=max(ans[y],query(1,1,n,s[x]+1,s[k])-s2[x]+w[x]);
59 }
60 calc_l(ls[k]);
61 update(1,1,n,s[k],-1e15);
62 calc_l(rs[k]);
63 }
64 void calc_r(int k){
65 if (!k)return;
66 if (!ls[k])update(1,1,n,s[k],s3[k]);
67 else update(1,1,n,s[k],mx[ls[k]]-s1[k]+s3[k]);
68 for(int i=0;i<vr[k].size();i++){
69 x=vr[k][i].first,y=vr[k][i].second;
70 ans[y]=max(ans[y],query(1,1,n,s[x]+1,s[k])-s3[x]+w[x]);
71 }
72 calc_r(rs[k]);
73 update(1,1,n,s[k],-1e15);
74 calc_r(ls[k]);
75 }
76 int main(){
77 scanf("%d%d",&n,&q);
78 for(int i=1;i<=n;i++)scanf("%d",&a[i]);
79 for(int i=1;i<=n;i++)scanf("%d",&w[i]);
80 for(int i=1;i<=n;i++){
81 while ((st[0])&&(a[st[st[0]]]<a[i]))ls[i]=st[st[0]--];
82 if (st[0])rs[st[st[0]]]=i;
83 st[++st[0]]=i;
84 }
85 mx[0]=-1e15;
86 dfs(st[1],0);
87 for(int i=1;i<=q;i++){
88 scanf("%d%d",&x,&y);
89 int z=lca(x,y);
90 ans[i]=max(s2[x]-s2[z],s3[y]-s3[z])+w[z];
91 if (x<z)vl[x].push_back(make_pair(z,i));
92 if (z<y)vr[y].push_back(make_pair(z,i));
93 }
94 for(int i=1;i<=n;i++)update(1,1,n,i,-1e15);
95 calc_l(st[1]);
96 calc_r(st[1]);
97 for(int i=1;i<=q;i++)printf("%lld\n",ans[i]);
98 }

[luogu5654]基础函数练习题的更多相关文章

  1. 6、50道JAVA基础编程练习题跟答案

    50道JAVA基础编程练习题 [程序1] 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 程序分析 ...

  2. 50道JAVA基础编程练习题

    50道JAVA基础编程练习题 [程序1] 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子对数为多少? 程序分析 ...

  3. 50道JAVA基础编程练习题 - 题目

    50道JAVA基础编程练习题[1]题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? [2]题目:判断 ...

  4. 【UOJ#228】基础数据结构练习题 线段树

    #228. 基础数据结构练习题 题目链接:http://uoj.ac/problem/228 Solution 这题由于有区间+操作,所以和花神还是不一样的. 花神那道题,我们可以考虑每个数最多开根几 ...

  5. 速战速决 (3) - PHP: 函数基础, 函数参数, 函数返回值, 可变函数, 匿名函数, 闭包函数, 回调函数

    [源码下载] 速战速决 (3) - PHP: 函数基础, 函数参数, 函数返回值, 可变函数, 匿名函数, 闭包函数, 回调函数 作者:webabcd 介绍速战速决 之 PHP 函数基础 函数参数 函 ...

  6. python基础——函数的参数

    python基础——函数的参数 定义函数的时候,我们把参数的名字和位置确定下来,函数的接口定义就完成了.对于函数的调用者来说,只需要知道如何传递正确的参数,以及函数将返回什么样的值就够了,函数内部的复 ...

  7. python基础—函数嵌套与闭包

    python基础-函数嵌套与闭包 1.名称空间与作用域 1 名称空间分为: 1 内置名称空间   内置在解释器中的名称 2 全局名称空间   顶头写的名称 3 局部名称空间 2 找一个名称的查找顺序: ...

  8. python基础—函数装饰器

    python基础-函数装饰器 1.什么是装饰器 装饰器本质上是一个python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能. 装饰器的返回值是也是一个函数对象. 装饰器经常用于有切 ...

  9. uoj #228. 基础数据结构练习题 线段树

    #228. 基础数据结构练习题 统计 描述 提交 自定义测试 sylvia 是一个热爱学习的女孩子,今天她想要学习数据结构技巧. 在看了一些博客学了一些姿势后,她想要找一些数据结构题来练练手.于是她的 ...

随机推荐

  1. gin 跨域问题

    package middlewares import ( "github.com/gin-gonic/gin" "net/http" ) func Cors() ...

  2. pycharm输入代码后,没有补全提示

    安装pycharm后,输入代码后,没有补全提示 首先检查是否关闭了代码提示,如下图,将红框中"Power Save Mode"前的勾去掉 第二步,如果在输入某些代码时还是没有补全提 ...

  3. 【UE4】GAMES101 图形学作业1:mvp 模型、视图、投影变换

    总览 到目前为止,我们已经学习了如何使用矩阵变换来排列二维或三维空间中的对象.所以现在是时候通过实现一些简单的变换矩阵来获得一些实际经验了.在接下来的三次作业中,我们将要求你去模拟一个基于CPU 的光 ...

  4. kiyv Button参数属性

    from kivy.uix.button import Button from kivy.uix.floatlayout import FloatLayout from kivy.app import ...

  5. 安装多个版本的 JDK

    安装多个版本的 JDK 刚刚开始学 Java 的时候安装了 JDK9 版本,后续发现还是 JDK8 使用的多些,而又不想删除原先版本 因此安装两个版本的 JDK 在需要是切换一下即可 1. 安装第一个 ...

  6. redis5集群搭建步骤

    通常情况下为了redis的高可用,我们一般不会使用redis的单实例去运行,一般都会搭建一个 redis 的集群去运行.此处记录一下 redis5 以后 cluster 集群的搭建. 一.需求 red ...

  7. 2021.8.11考试总结[NOIP模拟36]

    T1 Dove玩扑克 考场并查集加树状数组加桶期望$65pts$实际$80pts$,考后多开个数组记哪些数出现过,只扫出现过的数就切了.用$set$维护可以把被删没的数去掉,更快. $code:$ 1 ...

  8. Manacher(马拉车)

    Able was I ere I saw Elba.     ----Napoléon Bonaparte(拿破仑) 一.回文串&回文子串   这个很好理解. 如果一个字符串正着读和反着读是一 ...

  9. 【Golang详解】go语言中并发安全和锁

    go语言中并发安全和锁 首先可以先看看这篇文章,对锁有些了解 [锁]详解区分 互斥锁.⾃旋锁.读写锁.乐观锁.悲观锁 Mutex-互斥锁 Mutex 的实现主要借助了 CAS 指令 + 自旋 + 信号 ...

  10. 基础篇:JAVA集合,面试专用

    没啥好说的,在座的各位都是靓仔 List 数组 Vector 向量 Stack 栈 Map 映射字典 Set 集合 Queue 队列 Deque 双向队列 关注公众号,一起交流,微信搜一搜: 潜行前行 ...