洛谷4514 上帝造題的七分鐘(二維樹狀陣列)

2022-05-25 15:00:15 字數 1717 閱讀 4799

好久沒寫部落格了.....

這段時間狂補一下

題目大意:

給定乙個\(n*n\)的全0矩陣,每次有兩種操作:

\(l\ a\ b\ c\ d\ delta\) 表示將左上角\((a,b)\),右下角\((c,d)\)的矩陣加\(delta\)

\(k\ a\ b \ c \ d\) 表示求左上角\((a,b)\),右下角\((c,d)\)的矩陣的和並輸出

其中運算元\(\le 10^5\),\(n \le 2048\)

(此題卡空間,所以不要開\(long\ long\))

qwq既然是套路題,就直接說了

這個題考察的主要是二維樹狀陣列

首先,模擬一維,二維的樹狀陣列\(c[i][j]\)表示,第\(i\)行 向上 \(lowbit(i)\)行,第\(j\)列,向左\(lowbit(j)\)列的和是多少。

那麼修改也就顯而易見了

struct bit

} int query(int x,int y)

}return ans;

}};

然後,我們來考慮怎麼實現區間加呢?

一維的時候,我們運用的是差分的思想

那麼我們對於二維,不妨使用\(d[i][j]=a[i][j]-a[i-1][j]-a[i][j-1]+a[i][j]\)

那麼我們對於修改乙個\((x1,y1)->(x2,y2)\)的矩陣,我們只需要讓\(d[x1][y1]+=delta,d[x1][y2+1]-=delta,d[x2+1][y1]-=delta,d[x2+1][y2+1]+=delta\)

就可以輕鬆完成了qwq

那....要是用差分陣列,求和貌似就需要一點學問啊

對於求乙個\((1,1)->(x,y)\)的矩陣的和

就是\[ans = \sum_^ \sum_^\sum_^ \sum_^ d[h][k]

\]我們可以通過計算每個d的出現次數

來化簡這個式子

\[ans = \sum_^ \sum_^ d[i][j]*(x-i+1)*(y-j+1)

\]然後最終的式子就是

\[\sum_^ \sum_^ d[i][j]*(xy+x+y+1) - d[i][j]*i*(y+1)-d[i][j]*j*(x+1)+d[i][j]*i*j

\]那麼我們只需要維護四個樹狀陣列,就ok了

直接上**

// luogu-judger-enable-o2

#include#include#include#include#includeusing namespace std;

inline int read()

while (isdigit(ch))

return x*f;

}const int maxn = 2051;

int lowbit(int x)

int n,m;

struct bit

} int query(int x,int y)

}return ans;

}};bit ymh,ymhi,ymhj,ymhij;

char s[10];

int x1,x2,yy,y2;

void add(int x,int y,int p)

int sum(int x,int y)

signed main()

else

} return 0;

}

洛谷P4514 上帝造題的七分鐘

這是乙個二維區域修改區域查詢問題,可以考慮使用二維樹狀陣列解決。我們先回憶一下一維區間修改區間查詢樹狀陣列是怎麼做的,因為樹狀陣列本身只支援求字首和的形式,每次修改也只能單點修改,因此結合字首和和單點修改的性質,我們想到可以用樹狀陣列來維護差分陣列,這樣就能做到區間修改單點查詢,但這還是不是我們需要...

洛谷P4514 上帝造題的七分鐘

第一分鐘,x說,要有矩陣,於是便有了乙個裡面寫滿了 0 的 n times m 矩陣。第二分鐘,l說,要能修改,於是便有了將左上角為 a,b 右下角為 c,d 的乙個矩形區域內的全部數字加上乙個值的操作。第三分鐘,k說,要能查詢,於是便有了求給定矩形區域內的全部數字和的操作。第四分鐘,彩虹喵說,要基...

上帝造題的七分鐘2

xlk覺得 上帝造題的七分鐘 不太過癮,於是有了第二部。第一分鐘,x說,要有數列,於是便給定了乙個正整數數列。第二分鐘,l說,要能修改,於是便有了對一段數中每個數都開平方 下取整 的操作。第三分鐘,k說,要能查詢,於是便有了求一段數的和的操作。第四分鐘,彩虹喵說,要是noip難度,於是便有了資料範圍...