• 二维树状数组总结


    概念

    维护原二维数列的差分数列,从而用二维树状数组进行单点修改,求二维前缀和等操作,进而转化为区域加,区域求和等操作。

    例题

    [Luogu] P4514 上帝造题的七分钟

    (Link)

    Description

    (n imes{m})矩阵进行区域加,区域求和。((1≤n≤2048,1≤m≤2048,−500≤d≤500))

    Solution

    (egin{aligned}& ext {设} a_{x, y}=sum_{i=1}^{x} sum_{j=1}^{y} Delta a_{x, y}, ext { 则 }\&Delta a_{x, y}=a_{x, y}+a_{x-1, y-1}-a_{x, y-1}-a_{x-1, y} quad ext { (最终求区间和时同理})\&sum_{x=1}^{n} sum_{y=1}^{m} a_{x, y}=sum_{x=1}^{n} sum_{y=1}^{m} sum_{i=1}^{x} sum_{j=1}^{y} Delta a_{x, y}=sum_{x=1}^{n}(n-x+1) sum_{y=1}^{m}(m-y+1) Delta a_{x, y}\&=(n+1)(m+1) sum_{x=1}^{n} sum_{y=1}^{m} Delta a_{x, y}-(n+1) sum_{x=1}^{n} sum_{y=1}^{m} y Delta a_{x, y}-(m+1) sum_{x=1}^{n} sum_{y=1}^{m} x Delta a_{x, y}+sum_{x=1}^{n} sum_{y=1}^{m} x y Delta a_{x, y}\& ext { 二维树状数组维护 } sum_{x=1}^{n} sum_{y=1}^{m} Delta a_{x, y}, sum_{x=1}^{n} sum_{y=1}^{m} y Delta a_{x, y}, sum_{x=1}^{n} sum_{y=1}^{m} x Delta a_{x, y},sum_{x=1}^{n} sum_{y=1}^{m} x y Delta a_{x, y} ext { 即可 }end{aligned})

    Code

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define lowbit(x) ((x) & (-x))
    
    int n, m, t[2050][2050][5];
    
    char ch[2];
    
    int read()
    {
    	int x = 0, fl = 1; char ch = getchar();
    	while (ch < '0' || ch > '9') { if (ch == '-') fl = -1; ch = getchar();}
    	while (ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + ch - '0'; ch = getchar();}
    	return x * fl;
    }
    
    void add(int x, int y, int d, int tp)
    {
    	for (int i = x; i <= n; i += lowbit(i))
    		for (int j = y; j <= m; j += lowbit(j))
    			t[i][j][tp] += d;
    	return;
    }
    
    int ask(int x, int y, int tp)
    {
    	int sum = 0;
    	for (int i = x; i; i -= lowbit(i))
    		for (int j = y; j; j -= lowbit(j))
    			sum += t[i][j][tp];
    	return sum;
    }
    
    void modify(int x, int y, int d)
    {
    	add(x, y, d, 1); add(x, y, d * x, 2); add(x, y, d * y, 3); add(x, y, d * x * y, 4);
    	return;
    }
    
    int query(int x, int y)
    {
    	return (x + 1) * (y + 1) * ask(x, y, 1) - (y + 1) * ask(x, y, 2) - (x + 1) * ask(x, y, 3) + ask(x, y, 4);
    }
    
    int main()
    {
    	cin >> ch >> n >> m;
    	while (~scanf("%s", ch))
    	{
    		int a, b, c, d, x;
    		if (ch[0] == 'L')
    		{
    			cin >> a >> b >> c >> d >> x;
    			modify(a, b, x); modify(a, d + 1, -x); modify(c + 1, b, -x); modify(c + 1, d + 1, x);
    		}
    		else
    		{
    			cin >> a >> b >> c >> d;
    			int res = query(c, d) - query(c, b - 1) - query(a - 1, d) + query(a - 1, b - 1);
    			printf("%d
    ", res);
    		}
    	}
    	return 0;
    }
    

    [Luogu] CF341D Iahub and Xors

    (Link)

    Description

    (n imes{n})矩阵,(m)次进行区域异或(d),区域求异或和。((1≤n≤1000,1≤m≤10^5,0≤d≤2^{62}))

    Solution

    和上一题挺像的。注意到同一个数异或偶数次是(0),异或奇数次是它本身。

    Code

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define lowbit(x) ((x) & (-x))
    
    int n, m, t[2050][2050][5];
    
    char ch[2];
    
    int read()
    {
    	int x = 0, fl = 1; char ch = getchar();
    	while (ch < '0' || ch > '9') { if (ch == '-') fl = -1; ch = getchar();}
    	while (ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + ch - '0'; ch = getchar();}
    	return x * fl;
    }
    
    void add(int x, int y, int d, int tp)
    {
    	for (int i = x; i <= n; i += lowbit(i))
    		for (int j = y; j <= m; j += lowbit(j))
    			t[i][j][tp] += d;
    	return;
    }
    
    int ask(int x, int y, int tp)
    {
    	int sum = 0;
    	for (int i = x; i; i -= lowbit(i))
    		for (int j = y; j; j -= lowbit(j))
    			sum += t[i][j][tp];
    	return sum;
    }
    
    void modify(int x, int y, int d)
    {
    	add(x, y, d, 1); add(x, y, d * x, 2); add(x, y, d * y, 3); add(x, y, d * x * y, 4);
    	return;
    }
    
    int query(int x, int y)
    {
    	return (x + 1) * (y + 1) * ask(x, y, 1) - (y + 1) * ask(x, y, 2) - (x + 1) * ask(x, y, 3) + ask(x, y, 4);
    }
    
    int main()
    {
    	cin >> ch >> n >> m;
    	while (~scanf("%s", ch))
    	{
    		int a, b, c, d, x;
    		if (ch[0] == 'L')
    		{
    			cin >> a >> b >> c >> d >> x;
    			modify(a, b, x); modify(a, d + 1, -x); modify(c + 1, b, -x); modify(c + 1, d + 1, x);
    		}
    		else
    		{
    			cin >> a >> b >> c >> d;
    			int res = query(c, d) - query(c, b - 1) - query(a - 1, d) + query(a - 1, b - 1);
    			printf("%d
    ", res);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    《图像处理实例》 之 Voronoi 图
    《图像处理实例》 之 Voronoi 图
    《图像处理实例》 之 Voronoi 图
    Docker 1.13.0 详细更新日志
    Docker 1.13.0 详细更新日志
    Docker 1.13.0 详细更新日志
    Docker 1.13.0 详细更新日志
    Ubuntu上安装VMware tools
    Ubuntu上安装VMware tools
    Casper CBC 简要说明
  • 原文地址:https://www.cnblogs.com/andysj/p/14000999.html
Copyright © 2020-2023  润新知