2913

暴力遍历,on^3
最暴力的方法就是,枚举起点,然后枚举长度,之后维护内部出现的元素

但肯定还有更好的方法
线段树


如果这个题用线段树的话,是给定了一个固定的区间Nums,每个节点表示其所对应的区间上有多少个不一样的元素,每个叶子的值就是1;那关键在于怎么合并?以及最终查询,求和结果时如何求?


本题示例





过程就是不断枚举右端点,然后去区间更新线段树的值,等右端点枚举完了,结果就好了
首先对于线段树,其下标均为可能的左端点
然后在枚举右端点的时候,就是要去更改不大于它的所有线段树叶子,即合法的左端点,区间修改
枚举右端点,检查其值x,如果之前出现过,那么寻找其最后一次出现的位置prev,那么对于它之后的所有位置,x都相当于是最后出现的位置,都可以使其dl+1,而对前面出现过的位置,有他没他不影响值的更改,不变,所以是要区间批量修改prev+1,r
这样在枚举右端点时就会不断更新所有可能的区间,和直观理解的按区间长度来不断枚举的过程是不一样的,这个枚举右端点的过程,相当于是先固定一个端点再枚举长度来更新,只不过是批量的区间更新;然后按长度更新,就是枚举起点,然后再枚举长度更新
AI实现

这边参数是区间编号(保留这个参数是为了取值,即从线段树数组当中拿值出来)
对应原数组当中的左右端点(物理含义,但凭这个是找不到线段树当中的值的)
查询区间,以及更新值(这个题固定是1,所以也可以不要)
prev+1应当<=r,即至少是保留了r的一个情况,这个情况也是必然需要更改的
也就是说当调用update的时候,是一定会发生更改的,即判断是否应该更改的任务,不应该放在update方法里;调用Update时,至少会更改r的一种情况,即单点修改,左端点靠前,即prev+1<r时,就可能会修改多个情况(也包含了只有r时的情况)
以及最后的答案,由于是在枚举右端点,所以当右端点发生改变时,整个树上各节点的物理含义也会随之发生改变,不过既然如此,对于不同的右端点,线段树为什么都还是同一个?不该是每个右端点都对应一个自己的线段树吗?


就是说,在物理含义上,当枚举r时,对每个不同的r,线段树的物理含义确实不同,也确实可以说是不同的线段树,但当前r的线段树,可以由上个r-1的线段树简单地得到
然后最终的结果,就是这n个线段树最顶层区间结果的加和

复习线段树




对于区间修改,就是对所查询的那个区间,拼起来集体修改,如果要查询到单点,那就是查该单点时路过的所有区间落实修改,相当于修改延后,但也可能不会真的落实,以及可能会将多个区间修改合并在一起
