前缀和 & 差分

版权声明:支持原创,原作者地址:https://blog.csdn.net/qq_39824819 https://blog.csdn.net/qq_39824819/article/details/81841269
前缀和和差分,两个都是一种优化算法,把原来甚至需要O(n平方)的算法变成O(n),可谓优化得十分优秀。那它们俩具体是什么,我们一起来看

前缀和:

可基本分为一维前缀和和二维前缀和。

  1. 一维前缀和:设计状态f[i]表示i之前(包括i)符合条件的元素个数。这么说可能有些抽象,我们举个例子来看:有一个长度为n的序列,如果其中一个元素>=10,就算它是个“好元素”,有q组询问(x,y),请问对于每组询问x-y位置中有多少个好元素?看到这道题我们第一反应可能就是暴力枚举,一个一个找看是不是,是就++。但这样对于多组询问无疑TLE,所以我们就用f[i]表示i之前(包括i)符合条件的元素个数,然后开始递推,每次f[i]=f[i-1],如果它自己也符合条件,那么再f[i]++,最后递推完后,每一组询问的答案就是f[x]-f[y-1]
  2. 二维前缀和:设计状态f[i][j]表示以(i,j)为右下角的矩形内合法的元素个数,递推式就是:f[i][j]=f[i][j-1]+f[i-1][j]-f[i-1][j-1],如果它自己也符合条件,那么再f[i][j]++,为什么,画个图形就知道了

差分:

差分基本分为线性差分、树上差分,树上差分又分为点差分和边差分。

线性差分:差分适用与区间修改,你可能看到这会说:线段树!但是没有多次动态询问的题目,用线段树可真谓大材小用。差分是怎么支持区间修改的呢?我们首先设计一个差分数组diff和原数组a,diff[i]表示a[i]应该变化的量。所以假如有数列1、2、3、4、5,我现在要求你将位置2-位置4的每个元素加上3,这时用差分应该怎么做呢?首先diff[2]+=3,diff[4+1]-=3,为什么要这样呢?因为差分也有递推式:diff[i]+=diff[i-1],所以到时候位置2-4的元素都加了一个3,而第5个元素加了一个3又减了一个3,所以就为0了,后面的元素自然就为0。所以用差分解决区间修改问题的话,第一步对于每组要求:只用头尾加减即可,第二步要求执行完后递推差分数组,最后递推a数组,即a[i]+=diff[i]

树上差分:其实树上差分跟线性差分一样,它可以解决什么问题呢?举个例子,有一颗树V,里面有很多条链,请你找出被每条链都经过的公共边。看到这题,暴力我猜你也想到了,这样100%T飞,所以我们对于每条链的起点s和终点e和它们的lca,用一个差分数组diff,并diff[s]++,diff[e]++,diff[lca(s,e)]-=2,最后遍历一遍图(也就是线性差分的递推),得出diff[i],即边(i,i的爸爸)被访问过多少次。这么说太抽象了。我直接转别人的一个博客

  1. 树上差分讲解
  2. 树上差分模版题(题解)看作者为Sa开头的那篇

看了然后再做一遍题我相信你就懂了!

猜你喜欢

转载自blog.csdn.net/qq_39824819/article/details/81841269