zoukankan      html  css  js  c++  java
  • 差分讲解

    差分应用到解决题目中,主要是区间修改的问题。

    如果让你给区间[l,r]中的每一个数都加上x,一般情况下会直接暴力循环将每一个数都加上x。

    就像这样:

    1 void update(int l,int r,int x)
    2 {
    3     for(int i=l;i<=r;i++)
    4     {
    5         a[i]+=x;
    6     }
    7 }

    但是如果l-r非常大的话,这样做很明显时间复杂度很高,而差分则可以解决这个问题。

    首先看一下前缀和的概念,前缀和是前 i 个数的和,就有了前缀和数组presum[maxn],前缀和数组中的每一个元素都存储了对应数组a[maxn]中前 i 个数的和,也就是presum[i]=presum[i-1]+a[i](前i-1个数的和加上当前数)。

    差分可以说是和前缀和操作相反的,差分需要一个差分数组d[maxn],差分数组储存的是相邻元素的差,即d[i]=a[i] -a[i-1]。

    举个例子:比如数组a={1,2,3,4,5,6},那么前缀和数组是presum={1,3,6,10,15,21},差分数组d={1,1,1,1,1}(少一个)。

    构造差分数组的代码:(a数组是编号1-n的数组)

    1 void makediff(int n)
    2 {
    3     for(int i=2;i<=n;i++)
    4     {
    5         d[i]=a[i]-a[i-1];
    6     }
    7 }

    进行区间修改操作,只需要在l和r这两个端点处对差分数组进行修改,假如在区间[l,r],中每个数都加上x。

    那么将d[l]加上x,将d[r+1]减去x,因为是相邻的差,所以数a[r+1]-a[r]是差分数组d[r+1]的值,a[r+1]没变,而a[r]变了,所以..就这样。

    看代码:

    1 void update(int l,int r,int x)
    2 {
    3     d[l]+=x;
    4     d[r+1]-=x;
    5     return ;
    6 }

     要得到一个数a[i],需要推出这个数。

    从第1个数依托差分数组得到每一个a[i],或者直接到要查询的数就停也可以。

    代码如下:

    1 int getnum(int pos)
    2 {
    3     for(int i=1;i<=n;i++)
    4     {
    5         a[i]=a[i-1]+d[i];
    6     }
    7     return a[pos];
    8 }
  • 相关阅读:
    uva 11294 Wedding
    uvalive 4452 The Ministers’ Major Mess
    uvalive 3211 Now Or Later
    uvalive 3713 Astronauts
    uvalive 4288 Cat Vs. Dog
    uvalive 3276 The Great Wall Game
    uva 1411 Ants
    uva 11383 Golden Tiger Claw
    uva 11419 SAM I AM
    uvalive 3415 Guardian Of Decency
  • 原文地址:https://www.cnblogs.com/theshorekind/p/12681496.html
Copyright © 2011-2022 走看看