差分数组
差分数组
引入:
首先,给出一个问题:
给出n个数,再给出Q个询问,每个询问给出le,ri,x,最后再询问某个数,或者某个区间和(离线询问)
类似这样的问题,我们可以利用差分数组来解决。
假如这里有一个数组shu[n+1],其中shu[i]存储的便是某个具体的数
由前缀和数组的定义:\(sum[x] = \sum\limits_{i=1}^{x} shu[i]\)
类似地,我们给出差分数组的定义:d[i] = shu[i] - shu[i-1];
容易知道:
- \(shu[x] = \sum\limits_{i=1}^{x} d[i]\)
- \(shu[x] = \sum\limits_{i=1}^{x} shu[i] = \sum\limits_{i=1}^{x}\sum\limits_{j=1}^{i}d[j] = \sum\limits_{i=1}^{x}(x-i+1)*d[i]\)
3.对区间l到r同时加上s,只需要令d[l]+=s并且d[r+1]-=s即可维护,因此维护代价为O(1)
4.由1和2我们可以知道,通过差分数组能O(n)求出经过Q次维护的定点询问或区间询问(求出定点shu[n]就相当于求出所有定点,求出全区间就相当于所有区间了)
实战:
SP10500 HAYBALE - Haybale stacking
思路:构建差分数组,经过K次差分数组维护,最后将结果sort即可
AC代码如下:
#include <stdio.h>
#include <stdlib.h>
int com(const void *a, const void *b)
{
return *(int *)a - *(int *)b;
}
int main(void)
{
int n, k;
scanf("%d %d",&n,&k);
int shu[n+2], d[n+2];
for(int i = 1; i <= n; i++)
{
shu[i] = 0;
}
shu[0] = 0; //不要忘了边界
for(int i = 1; i <= n; i++)
{
d[i] = shu[i] - shu[i-1]; //构建差分数组
}
int a, b;
for(int i = 1; i <= k; i++)
{
scanf("%d %d",&a,&b);
d[a]++;
d[b+1]--;
}
for(int i = 1; i <= n; i++)
{
shu[i] = shu[i-1]+d[i];
}
qsort(shu+1, n, sizeof(int), com); //排序并输出中间的
printf("%d\n",shu[(n)/2+1]);
return 0;
}