返回顶部

差分数组

差分数组

引入:

首先,给出一个问题:
给出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];
容易知道:

  1. \(shu[x] = \sum\limits_{i=1}^{x} d[i]\)
  2. \(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;
}

posted on 2019-10-27 21:53  进击の辣条  阅读(228)  评论(0编辑  收藏  举报

导航