二维树状数组

eg:luogu P4514 上帝造题的七分钟

s 为前缀和数组,d 为差分数组,a 为原数组。

则:

sn,m=i=1nj=1mai,j

有:

ai,j=k=1nl=1jdk,l

所以:

sn,m=i=1nj=1mk=1il=1jdi,j

发现 d1,1 出现 n×m 次,d1,2 出现 n×(m1) 次,d2,2 出现 (n1)×(m1) 次,,总结规律,发现 dx,y 出现 (nx+1)×(my+1) 次。

所以原式变为:sn,m=i=1nj=1m(ni+1)×(mj+1)×di,j

展开:

sn,m=i=1nj=1m(nmnj+nmi+iji+mj+1)

合并同类项:

sn,m=i=1nj=1m[nmm(i1)n(j1)+(i1)(j1)]

展开:

sn,m=i=1nj=1mnm×di,ji=1nj=1mm(i1)×di,ji=1nj=1mn(j1)×di,j+i=1nj=1m(i1)(j1)×di,j

所以二维树状数组维护 di,j,(i1)×di,j,(j1)×di,j,(i1)(j1)×di,j 就可以了。

修改的话,二维差分即可。查询同理。因为二维树状数组和一维数状数组一样维护的是前缀和。

#include <bits/stdc++.h> using namespace std; const int N = (1 << 11) + 1; int n, m, f1[N][N], f2[N][N], f3[N][N], f4[N][N]; char c, opt; int lowbit(int x) { return x & -x; } void add(int x, int y, int k) { for (int i = x; i <= n; i += lowbit(i)) { for (int j = y; j <= m; j += lowbit(j)) { f1[i][j] += k; f2[i][j] += (x - 1) * k; f3[i][j] += (y - 1) * k; f4[i][j] += (x - 1) * (y - 1) * k; } } } int getsum(int x, int y) { int sum = 0; for (int i = x; i; i -= lowbit(i)) { for (int j = y; j; j -= lowbit(j)) { sum += f1[i][j] * x * y; sum -= f2[i][j] * y; sum -= f3[i][j] * x; sum += f4[i][j]; } } return sum; } int main() { cin >> c >> n >> m; while (cin >> opt) { int a, b, c, d, val; if (opt == 'L') { cin >> a >> b >> c >> d >> val; add(a, b, val); add(a, d + 1, -val); add(c + 1, b, -val); add(c + 1, d + 1, val); } else { cin >> a >> b >> c >> d; cout << getsum(c, d) - getsum(a - 1, d) - getsum(c, b - 1) + getsum(a - 1, b - 1) << endl; } } return 0; }

__EOF__

本文作者ようこそ!
本文链接https://www.cnblogs.com/ydq1101/p/17786419.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   ydq1101  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!
点击右上角即可分享
微信分享提示