您现在的位置是:主页 > news > 基于php的网站开发毕业论文/北京网站定制公司

基于php的网站开发毕业论文/北京网站定制公司

admin2025/6/13 20:01:22news

简介基于php的网站开发毕业论文,北京网站定制公司,怎么做美食团购网站,wordpress用户安全文章目录一、差分介绍与代码模板二、从差分到原数组三、一维差分的应用【区间加】四、一维差分应用拓展【区间加等差单点查询】五、二维差分六、总结一、差分介绍与代码模板 如果我们需要维护的数据是“两个相邻数据之差”,这就是差分。令diai−ai−1d_{i}a_{i}-a_…

基于php的网站开发毕业论文,北京网站定制公司,怎么做美食团购网站,wordpress用户安全文章目录一、差分介绍与代码模板二、从差分到原数组三、一维差分的应用【区间加】四、一维差分应用拓展【区间加等差单点查询】五、二维差分六、总结一、差分介绍与代码模板 如果我们需要维护的数据是“两个相邻数据之差”,这就是差分。令diai−ai−1d_{i}a_{i}-a_…

文章目录

  • 一、差分介绍与代码模板
  • 二、从差分到原数组
  • 三、一维差分的应用【区间加】
  • 四、一维差分应用拓展【区间加等差+单点查询】
  • 五、二维差分
  • 六、总结


一、差分介绍与代码模板

如果我们需要维护的数据是“两个相邻数据之差”,这就是差分。令di=ai−ai−1d_{i}=a_{i}-a_{i-1}di=aiai1,则称dddaaa的差分数组。也可以写成Δai=ai−ai−1\Delta a_{i} = a_{i} - a_{i-1}Δai=aiai1

差分的写法与前缀和专栏的那篇介绍文章差不多,我们使用的数据数组 aaa 和差分数组 ddd 都是从1开始:

【差分模板】:

void getDiff(int a[], int n) { //a[0]=0, 使用[1,n]for (int i = 1; i <= n; ++i) d[i] = a[i] - a[i - 1]; //d[0]=0 
}

二、从差分到原数组

其实从前缀和也可以很轻易的求出原数组,不过是求区间和的区间的左右两端点相等罢了(即a[i]=sum[i]−sum[i−1]a[i] = sum[i] - sum[i - 1]a[i]=sum[i]sum[i1])。

同样的思想,我们也可以拿着差分数组ddd推出aaa数组。而且a[i]=a[i−1]+d[i]a[i] = a[i - 1] + d[i]a[i]=a[i1]+d[i]aia_{i}ai相当于是差分数组ddd的前缀和sum[i]sum[i]sum[i] … 不说相当于,其实,aaa数组就是ddd数组的前缀和数组

如果要求aaa数组的区间和,怎么做呢?(^_^)

所以,从我们约定的前缀和的写法(方便递推求前缀和数组)和求差分这两种角度来看,就写a[0]=0a[0]=0a[0]=0

简单的举例:

a   : 0 | 3 7  5 8 (a[0]默认为0)
d   : 0 | 3 4 -2 3
sum : 0 | 3 7  5 8

很容易想明白,现在我在0楼,上了3楼,又上了4层楼,再往下走了两层楼,然后又上了三层楼,那么我现在位于0+3+4-2+3=8楼。

代码如下:

void getA(int p[], int n) { //d[0]=0, 使用[1,n]for (int i = 1; i <= n; ++i) a[i] = a[i - 1] + d[i];
}

前缀和可以让人以O(1)的时间求出一个区间的和。差分的用途也差不多,用来优化算法,甚至可以优化掉一个次方的复杂度。

下面具体介绍其应用。

三、一维差分的应用【区间加】

给定一个序列aaa,其初值全为0,有很多(m)次操作,允许离线,形如:AlrkA \quad l \quad r \quad kAlrk,将a[l,r]a_{[l,r]}a[l,r]中的每个值加上kkk。为方便,这里的l≥1,r≥1l \geq 1, r \geq 1l1,r1。最后输出整个数组,复杂度要求O(n)O(n)O(n)

举例如下:

a : 0 | 0 0 0 0 0 0A 1 2 3
-> a : 0 | 3 3 0 0 0 0A 2 5 -2
-> a : 0 | 3 1 -2 -2 -2 0A 5 6 3
-> a : 0 | 3 1 -2 -2 1 3

最简单的想法,就是对原数组进行操作,每次对区间[l,r][l,r][l,r]进行相应的操作,时间为O(mn)O(mn)O(mn),m很大时甚至会达到平方的复杂度。下面的做法,可以真正做到O(n)O(n)O(n)

不难发现,区间[l,r][l,r][l,r]加k,实际上发生了如下的两件事:

  • a[l]a[l]a[l]比前一个元素多了kkk
  • a[r+1]a[r + 1]a[r+1]比前一个元素少了kkk;(不用大了小了的说法,会引起误解)
    在这里插入图片描述

在差分数组ddd的基础上面,可以对应转换为两个操作:

  • d[l]+=kd[l] += kd[l]+=k
  • d[r+1]−=kd[r + 1] -= kd[r+1]=k

即,一次区间加,只修改这两个元素,区间内部的数据之间的差值没有变化,对应于差分数组相应区别不变。

最后利用上面的(求前缀和)方法,从ddd数组求出aaa数组,即为答案。

例子:

a : 0 | 0 0 0 0 0 0
d : 0 | 0 0 0 0 0 0A 1 2 3
-> a : 0 | 3 3  0 0 0 0
-> d : 0 | 3 0 -3 0 0 0A 2 5 -2
-> a : 0 | 3  1 -2 -2 -2 0
-> d : 0 | 3 -2 -3  0  0 2A 5 6 3
-> a : 0 | 3  1 -2 -2  1 3
-> d : 0 | 3 -2 -3  0  3 2  (r + 1 > n, 计不计算都行, p数组开大一些)

区间加

void add(int l, int r, int k) {d[l] += k;d[r + 1] -= k;
}void getA() {for (int i = 1; i <= n; ++i) //预先指定a[0]=0a[i] = a[i - 1] + d[i];

如果是单点加,用上面的add完全没问题:
dx+=k,dx+1−=k.d_{x} += k, d_{x+1} -= k.dx+=k,dx+1=k.

本质和区间加一模一样。


四、一维差分应用拓展【区间加等差+单点查询】

给定一个序列aaa,其初值全为0,有很多(m)次操作,操作有两种,强制在线,形如:

  • 区间加等差数列:AlrfwA \quad l \quad r \quad f \quad wAlrfw,将a[l,r]a_{[l,r]}a[l,r]中的每个元素,加上首项为fff、公差为www的等差数列对应的元素,即a[l]+=f1a_{[l]} += f_{1}a[l]+=f1a[l+1]+=f2a_{[l + 1]} += f_{2}a[l+1]+=f2,… 。
  • 单点查询:xxx ,求出axa_{x}ax

为方便,这里的l≥1,r≥1l \geq 1, r \geq 1l1,r1。最后输出整个数组。

e.g.e.g.e.g. 目前 a={1,2,3,3,3,3}a=\{1,2,3,3,3,3\}a={1,2,3,3,3,3},给 [3,5][3,5][3,5] 加上首项为 222 、公差为 111 的等差数列,aaa 变为 {1,2,5,6,7,3}\{1,2,5,6,7,3\}{1,2,5,6,7,3}

原来的 d={1,1,1,0,0,0}d=\{1,1,1,0,0,0\}d={1,1,1,0,0,0},修改后的 ddd 数组:{1,1,3,1,1,−4}\{1,1,3,1,1,-4\}{1,1,3,1,1,4}。显然:aaa 区间加等差,相当于 ddd 区间加常数、端点单点修改

我们自然要把 d[l+1,r]d_{[l + 1,r]}d[l+1,r] 加上 wwwdld_{l}dl 加上 f1f_{1}f1 ;那么右端点呢?要把刚才的操作复原dr+1−=f1+(r−l)wd_{r+1} -= f_{1} + (r - l)wdr+1=f1+(rl)w

因此,我们要解决的问题在于,维护 ddd 数组,支持单点修改、区间加,可以使用线段树或者差分+树状数组(比如 ddd 的差分数组 d′={1,0,0,−1,0,0}d' = \{1,0,0,-1,0,0\}d={1,0,0,1,0,0} ,修改后的 d′={1,0,2,−2,0,−5}d' = \{1, 0, 2, -2, 0, -5\}d={1,0,2,2,0,5} ,对 aaa 加上等差数列,相当于对 ddd 单点修改端点、区间加等差 www ,相当于对 d′d'd 单点修改端点、单点修改区间端点)加以解决。

五、二维差分

二维差分不过是在一维差分之上,又加了一维而已。它的递推公式如下:
d[i][j]=a[i][j]−a[i][j−1]−a[i−1][j]+a[i−1][j−1]d[i][j] = a[i][j] - a[i][j - 1] - a[i- 1][j] + a[i - 1][j - 1]d[i][j]=a[i][j]a[i][j1]a[i1][j]+a[i1][j1]

当前元素减去左边元素再减去上边元素再加上左上角元素

由二维差分数组求出原数组,只需要求出二维前缀和即可。这样一来,通过二维差分可以快速实现矩阵加减(二维区间加减)。

六、总结

这里介绍了简单的差分思想,还有区间加二次函数,多次差分,树上差分,有限微积分…