[CodeForces #80 Div 1 D] 分块+树状数组/线段树

Part 1 题解

题意

给出一个长度为N(300000) 的数列ai ,再给出M 个询问,每个询问是形如(x,y) 的形式,你需要输出ax+ax+y+ax+2y+...+ax+ky 的和,其中x+(k+1)y>N

分析

PS:这道题的做法是对大小进行分块

对于每个询问,首先我们想到的方法是依次将axax+y ,…,ax+ky 来相加。
但是这样会TLE。

我们应该想一下出现超时的原因,并从这方面加以改进。
超时的原因:y 可能非常的小,加的次数非常的多。

那么我们可以设一个数T=H(n) ,即Tn 的一个函数。
对于y>T ,直接使用上述方法,时间复杂度为O(n2T)
对于y<T ,要想出另外一种方法。

y 小带来的特殊性就是可以存储下来预处理而不使空间太大。
我们先预处理出ans[x][y] 表示询问(x,y) 的答案。
具体的做法是枚举每一个y ,然后将x 从大到小枚举递推答案,则有:
ans[x][y]=ans[x+y][y]+a[x]
预处理的时间复杂度为O(nT) ,查询一次的复杂度为O(1)

所以总的时间复杂度为O(nT+n2T)
nT=n2TT=n 时,取得最小值。
所以总的时间复杂度为O(nn) ,空间复杂度为O(nn)

Part 2 变式一

题目

给出一个长度为N(300000) 的数列ai ,再给出M 个操作:
① A x d:将ax 加上d
② Q x y:询问ax+ax+y+ax+2y+...+ax+ky 的和,其中x+(k+1)y>N

分析

在原题的基础上,只需要对操作①进行维护即可。

对于操作① A x d:
首先将ax 赋值为ax+d
然后考虑ax 的改变对于ans[i][j] 的影响。

我们枚举j
对于相同的j ,所有k<iik 关于j 同类。都有ans[k][j] 增大了d

不属于这个类的,统计的时候也不会用到。
那就是——区间增值?
当然可以。

我们对每个T 开一个树状数组,对于操作A x d,枚举所有的类1T ,然后将这个类的前x 位都增大d 即可。

T=n 时,总的时间复杂度为O(nnlogn)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章