影魔

这一道题目有一个非常重要的思想,就是确定一个基准

就像计数题目一样,我们将一个区间确定一个基准,我们一般用端点作为基准,然而这道题目却行不通

但是这道题目的题干却一直提到最大值,所以我们以一个区间的最大值为基准,显然可以唯一确定

那么就不难确定一个区间\([a,b]\),以\((a,b)\)的最大值为基准

所以我们对每一个数,求出它左边和右边距离他最近的又比他大的数(单调栈)

然后按照题解处理即可(看到无修改,可以想到离线)

解释一下他这个处理方法,考虑\([l,r]\)这个区间所有点的贡献所包含的类型只有题解中说到的三种类型。对于题解中提到的\(sum_2\),包含所有三种类型的和,然而此时有些第三种类型产生的贡献我们是不想要的(左端点小于\(l\)),于是我们只用在进入\(l\)之前统计一下这些端点所产生的贡献就好了(这个思想跟“校门外的树”一样)

也可以用类似于HH的项链的方法,我们的代码用的是这个方法

这两种方法都要记下来,我们对第二种方法更加熟悉,然而第一种方法也是有应用的,比如在某些子树的统计题目里面:进入子树之前记录数组值,递归完之后准备出去的时候再记录数组值,相减即得答案

update 2024.5.16

我们也可以以区间的端点作为基准,下面以第一类贡献为例讨论

我们仍然像上面这样处理处\(L\)\(R\)数组,然后从左往右扫描,当我们扫描到\(r\)这个点的时候,有可能产生贡献的区间左端点的范围就是\([r-L[r],r-1]\),我们只用再在这些点中统计出有多少点\(i\)满足\(i+R[i]≥r\)即可

如果我们已经维护好了一个序列,若第\(i\)个位置的值为,那么直接用树状数组查询前缀和就好了;在我们从\(r\)变成\(r+1\)的时候,我们只用把所有满足\(i+R[i]=r\)的位置的值变为\(0\)就好了,并且将\([r+1,r+1+R[r+1]-1]\)的位置全部变\(1\),也可以用树状数组做到

还有一个问题,就是这道题目的询问是某一个区间,此时就要像题解那样子处理:对于一个区间\([l,r]\),在扫描到\(l-1\)的时候统计此时区间\([l,r]\)的总和,之后减掉就好了

以上做法有问题,可以想一下应该怎么做

posted @ 2023-12-23 18:45  最爱丁珰  阅读(13)  评论(0)    收藏  举报