例题:HDU 1556 传送门
题目大意:给你n个排成一排的气球,标号1,2,3…n。接下来执行n次操作,每次给出两个数a,b,将[a,b]内的气球涂一次颜色。最后问你每个气球分别被涂了几次颜色。
这题最暴力的写法就是每次拿到[a,b]区间就for遍历+1,但是操作数稍微多了就会T,这时候,我们就可以用到差分数组,差分数组就是用来解决区间修改和区间查询的操作的。(前提是修改与查询分开,也就是先执行若干次修改,再执行若干次查询,两者不能混合进行)
差分数组:
假设现在有一个数组a[6]
={0,2,7,5,1,6}
差分数组b
:
b[0]=a[0]
b[i]=a[i]-a[i-1](i>=1)
也就是说b[6]
={0,2,5,-2,-4,5}
那么知道一个数组a的差分数组b有什么用呢?
1.执行连续区间的修改操作时:
例如我们现在对a数组的[2,4]的数都加上k,那么就有a[6]
={0,2,7+k,5+k,1+k,6},此时,我们再来观察差分数组b的变化,b[6]
={0,2,5+k,-2,-4,5-k}。可以看到,数组a的[i,j]
区间修改,需要遍历a[i]
到a[j]
,而差分数组b只需改变b[i]和b[j+1]即可。当需要对区间[i,j]
做+k
的操作时,只需对差分数组做b[i]+k,b[j+1]-k即可。证明也很容易,不赘述。
2.执行连续区间的查询操作时:
我们先来看看一个数组a[6]={a,b,c,d,e,f},差分数组b[6]={a,b-a,c-b,d-c,e-d,f-e},我们再来求一下差分数组b的前缀和SUM[6]看看,SUM[6]={a,b,c,d,e,f},可以发现差分数组的前缀和就是原来的数组a。这时,无论是做单点查询(直接输出SUM数组元素),还是做区间查询(对SUM数组再做一次前缀和)都很方便。