zoukankan      html  css  js  c++  java
  • poj_1190 树状数组

    题目大意

        给定一个S*S的矩形,该矩形由S*S个1x1的单元格构成,每个单元格内可以放一个整数,每次有如下可能操作: 
    (1)改变某个单位单元格中的数的大小 
    (2)查询由若干个连续单元格构成的X*Y的大小的矩形内所有数的总和

    题目分析

        典型的区间操作,而且是单点更新,区间查询。因此使用树状数组,不过应该使用二维树状数组。二维树状数组和一维其实没什么区别。。。。 
        另:用线段树也做了一份,但是超时,果然树状数组在效率上还是略胜线段树的。下面给出树状数组的AC代码和线段树的TLE代码。

    实现(c++)

    1.树状数组

    #define _CRT_SECURE_NO_WARNINGS
    #include<stdio.h>
    #include<string.h>
    #define MAX_SQUARE_SIZE 1025
    #define MAX(a, b) a>b? a:b
    #define MIN(a, b) a <b? a:b
    int gLowBit[MAX_SQUARE_SIZE];
    int gC[MAX_SQUARE_SIZE][MAX_SQUARE_SIZE];
    
    void InitLowBit(int n){
    	for (int i = 1; i <= n; i++){
    		gLowBit[i] = i&(-i);
    	}
    }
    
    void InitSequence(int n){
    	memset(gC, 0, sizeof(gC));
    }
    
    void Update(int x, int y, int n, int add){
    	int tmp_y = y;
    	while (x <= n){
    		y = tmp_y;
    		while (y <= n){
    			gC[x][y] += add;
    			y += gLowBit[y];
    		}
    		x += gLowBit[x];
    	}
    }
    int Query1(int x, int y){
    	int tmp_y = y, result = 0;
    	while (x > 0){
    		y = tmp_y;
    		while (y > 0){
    			result += gC[x][y];
    			y -= gLowBit[y];
    		}
    		x -= gLowBit[x];
    	}
    	return result;
    }
    
    int Query(int left, int right, int bottom, int top){
    	int r_t = Query1(right, top);
    	int l_t = Query1(left - 1, top);
    	int r_b = Query1(right, bottom - 1);
    	int l_b = Query1(left - 1, bottom - 1);			//注意在查询的时候,需要计算的矩形的边界弄清楚 [i , ... j] = sum(j) = sum(i - 1)
    	return (r_t + l_b - l_t - r_b);
    }
    int main(){
    	int ins;
    	int S, X, Y, A, L, B, R, T;
    	scanf("%d %d", &ins, &S);
    	InitLowBit(S);
    	InitSequence(S);
    	while (scanf("%d", &ins)){
    		if (ins == 3){
    			break;
    		}
    		if (ins == 1){
    			scanf("%d %d %d", &X, &Y, &A);
    			Update(X+1, Y+1, S, A);
    		}
    		else if (ins == 2){
    			scanf("%d %d %d %d", &L, &B, &R, &T);
    			int result = Query(L+1, R+1, B+1, T+1);
    			printf("%d
    ", result);
    		}
    	}
    	return 0;
    }
    

     2.线段树

    #define _CRT_SECURE_NO_WARNINGS
    #include<stdio.h>
    #define MAX_SQUARE_SIZE 1025
    #define MAX_NODE_NUM MAX_SQUARE_SIZE*4
    #define MAX(a, b) a>b? a:b
    #define MIN(a, b) a <b? a:b
    struct Node{
    	short left;
    	short right;
    	short top;
    	short bottom;
    	int sum_phones;
    	short h_mid(){
    		return (left + right) >> 1;
    	}
    	short v_mid(){
    		return (top + bottom) >> 1;
    	}
    };
    Node gNodes[MAX_NODE_NUM][MAX_NODE_NUM];
    void BuildTree(int h_index, int v_index, short left, short right, short bottom, short top){
    	gNodes[h_index][v_index].left = left;
    	gNodes[h_index][v_index].right = right;
    	gNodes[h_index][v_index].top = top;
    	gNodes[h_index][v_index].bottom = bottom;
    	gNodes[h_index][v_index].sum_phones = 0;
    	if (left == right || top == bottom){
    		return;
    	}
    	int left_child = 2 * h_index + 1, right_child = 2 * h_index + 2;
    	int up_child = 2 * v_index + 1, down_child = 2 * v_index + 2;
    	short h_mid = (left + right) >> 1, v_mid = (top + bottom) >> 1;
    	BuildTree(left_child, down_child, left, h_mid, bottom, v_mid);
    	BuildTree(right_child, down_child, h_mid + 1, right, bottom, v_mid);
    	BuildTree(left_child, up_child, left, h_mid, v_mid + 1, top);
    	BuildTree(right_child, up_child, h_mid + 1, right, v_mid + 1, top);
    }
    
    void Update(int h_index, int v_index, short left, short right, short bottom, short top, int add){
    	if (gNodes[h_index][v_index].left == gNodes[h_index][v_index].right){ //arrive to the point
    		gNodes[h_index][v_index].sum_phones += add;
    		return;
    	}
    	if (left > gNodes[h_index][v_index].right || right < gNodes[h_index][v_index].left
    		|| top < gNodes[h_index][v_index].bottom || bottom > gNodes[h_index][v_index].top){
    		return;
    	}
    	if (left > right || bottom > top){
    		return;
    	}
    	int left_child = 2 * h_index + 1, right_child = 2 * h_index + 2;
    	int up_child = 2 * v_index + 1, down_child = 2 * v_index + 2;
    	short h_mid = gNodes[h_index][v_index].h_mid(), v_mid = gNodes[h_index][v_index].v_mid();
    	gNodes[h_index][v_index].sum_phones += add;
    	Update(left_child, down_child, left, MIN(right, h_mid), bottom, MIN(top, v_mid), add);
    	Update(left_child, up_child, left, MIN(right, h_mid), MAX(v_mid + 1, bottom), top, add);
    	Update(right_child, down_child, MAX(left, h_mid + 1), right, bottom, MIN(top, v_mid), add);
    	Update(right_child, down_child, MAX(left, h_mid + 1), right, MAX(v_mid + 1, bottom), top, add);
    }
    
    int Query(int h_index, int v_index, short left, short right, short bottom, short top){
    	if (left == right || top == bottom){ //arrive to the point
    		return gNodes[h_index][v_index].sum_phones;
    	}
    	if (left > gNodes[h_index][v_index].right || right < gNodes[h_index][v_index].left
    		|| top < gNodes[h_index][v_index].bottom || bottom > gNodes[h_index][v_index].top){
    		return 0;
    	}
    	if (left > right || bottom > top){
    		return 0;
    	}
    	int left_child = 2 * h_index + 1, right_child = 2 * h_index + 2;
    	int up_child = 2 * v_index + 1, down_child = 2 * v_index + 2;
    	short h_mid = gNodes[h_index][v_index].h_mid(), v_mid = gNodes[h_index][v_index].v_mid();
    	int result = 0;
    	result += Query(left_child, down_child, left, MIN(right, h_mid), bottom, MIN(top, v_mid));
    	result += Query(left_child, up_child, left, MIN(right, h_mid), MAX(v_mid + 1, bottom), top);
    	result += Query(right_child, down_child, MAX(left, h_mid + 1), right, bottom, MIN(top, v_mid));
    	result += Query(right_child, down_child, MAX(left, h_mid + 1), right, MAX(v_mid + 1, bottom), top);
    	return result;
    }
    
    int main(){
    	int ins;
    	int S, X, Y, A, L, B, R, T;
    	scanf("%d %d", &ins, &S);
    	BuildTree(0, 0, 0, S - 1, 0, S - 1);
    	while (scanf("%d", &ins)){
    		if (ins == 3){
    			break;
    		}
    		if (ins == 1){
    			scanf("%d %d %d", &X, &Y, &A);
    			Update(0, 0, X, X, Y, Y, A);
    		}
    		else if (ins == 2){
    			scanf("%d %d %d %d", &L, &B, &R, &T);
    			int result = Query(0, 0, L, R, B, T);
    			printf("%d
    ", result);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    java算法--循环队列
    java算法--普通队列
    java算法--稀疏数组
    HelloWorld
    css
    自定义事件并且主动触发
    数组字符串操作
    进阶路上有你我-相互相持篇之ES6里箭头函数里的this指向问题
    关于一道面试题
    异步函数回调
  • 原文地址:https://www.cnblogs.com/gtarcoder/p/4787756.html
Copyright © 2011-2022 走看看