日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

线性结构 —— 前缀和

發(fā)布時(shí)間:2025/3/17 编程问答 12 豆豆
生活随笔 收集整理的這篇文章主要介紹了 线性结构 —— 前缀和 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

【概述】

前綴和是一種及其優(yōu)秀的線性結(jié)構(gòu),也是一種重要的思想,能極大的降低區(qū)間查詢的時(shí)間復(fù)雜度。

前綴和又分為一維前綴和、二維前綴和,其與差分?jǐn)?shù)組密切相關(guān),關(guān)于差分?jǐn)?shù)組:點(diǎn)擊這里

【一維前綴和】

假設(shè)有一串長(zhǎng)度為 n 的序列,再給出 m 次詢問,每次詢問給出 L、R 兩個(gè)數(shù),要求求出區(qū)間?[L,R] 的和,如果不使用前綴和的話,每次都遍歷一遍給出的區(qū)間,計(jì)算出答案,這樣時(shí)間復(fù)雜度會(huì)達(dá)到 O(n*m),極有可能會(huì) TLE,而使用前綴和來做的話,能將時(shí)間復(fù)雜度降到 O(n+m),極大的減少了時(shí)間。

前綴和的第 i 項(xiàng)就是一個(gè)序列前面 i 個(gè)數(shù)的總和,在一個(gè)序列經(jīng)過 n?次求和次操作后,對(duì)于 m 次詢問,每次只需要計(jì)算 sum[R]-sum[L-1] 即可得到所需的答案。

前綴和求法如下:

sum[0]=0; for(int i=1;i<=n;i++)sum[i]=sum[i-1]+a[i];

對(duì)于已求出的前綴和,區(qū)間 [L,R] 的和即為:res=sum[R]-sum[L-1]

int query(int L,int R){return sum[R]-sum[L-1]; }

對(duì)于異或操作,其符合前綴和性質(zhì),有:?a[l] ^ a[l+1]?^ a[l+2]...?^ a[r] = a[r],因此,如要求異或和的最大連續(xù)子段和,有:

int query(){int res=0;for(int i=1; i<=n; i++)for(int j=i; j<=n; j++)res=max(res,sum[j]^sum[i-1]);return res; }

當(dāng)給出 m 個(gè)操作,要求將區(qū)間 [L,R] 中的所有元素都加/減 x,再給出 q 個(gè)詢問求 [L,R] 的和,這個(gè)時(shí)候就利用上了差分?jǐn)?shù)組,開一個(gè)數(shù)組 f 作為差分?jǐn)?shù)組,存儲(chǔ)每一次的修改操作,最后在求前綴和的時(shí)候進(jìn)行統(tǒng)計(jì),即可得到答案

int n,m,q; int a[N]; int f[N],sum[N]; void update(int L,int R,int x){f[L]+=x;f[R+1]-=x; } void init(){//求前綴和int tot=0;for(int i=1;i<=n;i++){//通過差分?jǐn)?shù)組計(jì)算新序列tot+=f[i];a[i]=a[i]+tot;}for(int i=1;i<=n;i++)sum[i]=sum[i-1]+a[i]; } int query(int L,int R){//查詢區(qū)間return sum[R]-sum[L-1]; } int main(){cin>>n>>m>>q;for(int i=1;i<=n;i++)//輸入序列cin>>a[i];while(m--){//m個(gè)操作int l,r,x;cin>>l>>r>>x;update(l,r,x);}init();//獲取前綴和while(q--){//q次詢問int l,r;cin>>l>>r;cout<<query(l,r)<<endl;}return 0; }

【二維前綴和】

假設(shè)有一個(gè) n*m 大小的矩陣 A,再給出有 q 次詢問,每次詢問給出 x1、y1、x2、y2 四個(gè)數(shù),要求輸出以 (x1,y1) 為左上角坐標(biāo)和以 (x2,y2) 為右下角坐標(biāo)的子矩陣的所有元素和。?

同一維前綴和一樣,如果對(duì)于每次詢問都進(jìn)行暴力查詢,那么時(shí)間復(fù)雜度極大,一定會(huì) TLE,此時(shí)可以利用二維前綴和來求解。

以上圖中 a[3][3]=13?為例,a[3][3] 的前綴和,是以黑框框起來的子矩陣元素之和,從遞推的角度來看,sum[3][3]=sum[3][2]+sum[2][3]-sum[2][2],以此類推,有:sum[i][j]=sum[i][j-1]+sum[i-1][j]-sum[i-1][j-1]+a[i][j]

int sum[N][N]; void init(){for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)sum[i][j]=sum[i][j-1]+sum[i-1][j]-sum[i-1][j-1]+a[i][j]; }

如上文敘述,每次要查詢的答案是上圖中黃色的部分,可以看出,黃色=四個(gè)區(qū)域-(藍(lán)色+綠色)-(藍(lán)色+紅色)+藍(lán)色,那么當(dāng)給出 x1、y1、x2、y2 時(shí),要查詢的值即為:res=sum[x2][y2]-sum[x1-1][y2]-sum[x2][y2-1]+sum[x1-1][y-1]

int query(int x1,int y1,int x2,int y2){return sum[x2][y2]-sum[x1-1][y2]-sum[x2][y1-1]+sum[x1-1][y1-1]; }

?

與一維前綴和相同,當(dāng)給出 k 個(gè)操作,要求將以 (x1,y1) 為左上角 (x2,y2) 為右上角的子矩陣中的所有元素都加/減 x,再給出 q 個(gè)詢問子矩陣的和,這個(gè)時(shí)候就利用上了差分?jǐn)?shù)組,開一個(gè)數(shù)組 f 作為差分?jǐn)?shù)組,存儲(chǔ)每一次的修改操作,最后在求前綴和的時(shí)候進(jìn)行統(tǒng)計(jì),即可得到答案

int n,m,k,q; int a[N][N]; int sum[N][N]; int f[N][N]; int query(int x1,int y1,int x2,int y2) { //查詢r(jià)eturn sum[x2][y2]-sum[x1-1][y2]-sum[x2][y1-1]+sum[x1-1][y1-1]; } void update(int x1,int y1,int x2,int y2,int x) { //更新f[x1][y1]+=x;f[x1][y2+1]-=x;f[x2+1][y2+1]+=x;f[x2+1][y1]-=x; } void init() { //求前綴和int tot=0;for(int i=1; i<=n; i++) { //通過差分?jǐn)?shù)組計(jì)算新序列for(int j=1; j<=m; j++) {tot+=f[i][j];a[i][j]=a[i][j]+tot;}}for(int i=1; i<=n; i++)for(int j=1; j<=m; j++)sum[i][j]=sum[i][j-1]+sum[i-1][j]-sum[i-1][j-1]+a[i][j]; } int main() {cin>>n>>m>>k>>q;for(int i=1; i<=n; i++)for(int j=1; j<=m; j++)cin>>a[i][j];while(k--) { //k次操作int x1,y1,x2,y2,x;cin>>x1>>y1>>x2>>y2>>x;update(x1,y1,x2,y2,x);}init();//求前綴和while(q--) { //q次查詢int x1,y1,x2,y2;cin>>x1>>y1>>x2>>y2;int res=query(x1,y1,x2,y2);}return 0; }

【例題】

  • 最長(zhǎng)配對(duì)(51Nod-2494):點(diǎn)擊這里
  • 和為S(51Nod-2518):點(diǎn)擊這里
  • 和為k的倍數(shù)(51Nod-2522):點(diǎn)擊這里
  • Splitting Pile(AtCoder-2654):點(diǎn)擊這里
  • Weather(CF-234C):點(diǎn)擊這里
  • Little Xor(CF-252A)(異或前綴和):點(diǎn)擊這里
  • RGB Substring (hard version) (CF-1196D2)(前綴和+區(qū)間最小值):點(diǎn)擊這里
  • 01串(51Nod-1391)(前綴和+最長(zhǎng)長(zhǎng)度):點(diǎn)擊這里
  • 和為k的連續(xù)區(qū)間(51Nod-1094)(前綴和+連續(xù)區(qū)間):點(diǎn)擊這里
  • キャンディーとN人の子供 / Children and Candies(AtCoder-2021)(前綴和+線性DP):點(diǎn)擊這里
  • Checker(AtCoder-3876)(二維前綴和):點(diǎn)擊這里
  • 小a的轟炸游戲(2019牛客寒假算法基礎(chǔ)集訓(xùn)營(yíng) Day1-E)(二維前綴和):點(diǎn)擊這里
  • 海嘯(2019牛客寒假算法基礎(chǔ)集訓(xùn)營(yíng) Day6-E)(二維前綴和+lowbit):點(diǎn)擊這里
  • Table with Letters-2(CF-253D)(二維前綴和+有技巧的枚舉):點(diǎn)擊這里
  • 循環(huán)數(shù)組最大字段和(51Nod-1050)(deque+前綴和):點(diǎn)擊這里
  • Lines(HDU-5124)(pair+前綴和):點(diǎn)擊這里
  • 新人創(chuàng)作打卡挑戰(zhàn)賽發(fā)博客就能抽獎(jiǎng)!定制產(chǎn)品紅包拿不停!

    總結(jié)

    以上是生活随笔為你收集整理的线性结构 —— 前缀和的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。