设 a 是原数组,b 是一阶差分数组,c 是二阶差分数组。
b 的定义:bi={ai−ai−1a1i>1i=1
c 的定义:ci={bi−bi−1b1i>1i=1
考虑在区间 [l,r] 内对原数组加上首项为 s,公差为 d,末项 t=s+(r−l)d 的等差数列对 a 的影响:
ax′←ax+s+(x−l)d,(x∈[l,r])
考虑 a 的变化对 b 的影响:
bl′←al′−al−1←al−1+bl+s+(l−l)d−al−1←bl+s
bx′←ax′−ax−1′←ax−1+bx+s+(x−l)d−[ax−1+s+(x−1−l)d]←bx+d,
(x∈[l+1,r])
br+1′←ar+1−ar′←ar+br+1−[ar+s+(r−l)d]←br+1−t
考虑 b 的变化对 c 的影响:
cl′←bl′−bl−1←bl−1+cl+s−bl−1←cl+s
cl+1′←bl+1′−bl′←bl+cl+1+d−(bl+s)←cl+1+d−s
cx′←bx′−bx−1′←bx−1+cx+d−(bx−1+d)←cx,(x∈[l+2,r])
(重要的发现:cx 保持不变)
cr+1′←br+1′−br′←br+cr+1−t−(br+d)←cr+1−t−d
cr+2′←br+2−br+1′←br+1+cr+2−(br+1−t)←cr+2+t
每次操作都只会改变 c 上 4 个位置的值,因此可以 O(1) 时间实现区间加等差数列。
根据定义,
∵ci={bi−bi−1b1i>1i=1
∴bi=j=1∑icj
∵bi={ai−ai−1a1i>1i=1
∴ai=j=1∑ibj=j=1∑ik=1∑jck
// 在区间 [l,r] 加上首项为 s, 公差为 d 的等差数列
void add(int l, int r, int s, int d) {
int t = s + (r - l) * d;
c[l] += s;
c[l + 1] += d - s;
c[r + 1] -= t + d;
c[r + 2] += t;
}
int ask(int k) { // 查询 a_k 的值
int a = 0, b = 0;
for(int i = 1; i <= k; i++)
a += (b += c[i]);
return a;
}