好久沒寫部落格了.....
這段時間狂補一下
題目大意:
給定乙個\(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難度,於是便有了資料範圍...