BZOJ1452 [JSOI2009]Count 树状数组

欢迎访问~原文出处——博客园-zhouzhendong

去博客园看该题解


 题目传送门 - BZOJ1452


题意概括

  一个n*m的矩阵,现在有2种操作:

  1. 修改某一个位置的值
  2. 求一个子矩阵某值的出现次数

  n , m ≤ 300 ,  1 ≤ 元素的值 ≤ 100 , 操作次数 ≤ 200000


题解

  100棵二维树状数组。维护每个值的二维前缀出现次数。

  好像该说的都说了……


代码

#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstdio>
using namespace std;
const int N=300+5,C=100+5;
int n,m,q,a[N][N],t[C][N][N];
int lowbit(int x){
	return x&-x;
}
void add(int c,int x,int y,int d){
	for (int i=x;i<=n;i+=lowbit(i))
		for (int j=y;j<=m;j+=lowbit(j))
			t[c][i][j]+=d;
}
int sum(int c,int x,int y){
	int ans=0;
	for (int i=x;i>0;i-=lowbit(i))
		for (int j=y;j>0;j-=lowbit(j))
			ans+=t[c][i][j];
	return ans;
}
int main(){
	scanf("%d%d",&n,&m);
	memset(t,0,sizeof t);
	for (int i=1;i<=n;i++)
		for (int j=1;j<=m;j++){
			scanf("%d",&a[i][j]);
			add(a[i][j],i,j,1);
		}
	scanf("%d",&q);
	while (q--){
		int type,c;
		scanf("%d",&type);
		if (type==1){
			int x,y;
			scanf("%d%d%d",&x,&y,&c);
			add(a[x][y],x,y,-1);
			a[x][y]=c;
			add(a[x][y],x,y,1);
		}
		else {
			int x1,y1,x2,y2;
			scanf("%d%d%d%d%d",&x1,&x2,&y1,&y2,&c);
			printf("%d\n",sum(c,x2,y2)-sum(c,x1-1,y2)-sum(c,x2,y1-1)+sum(c,x1-1,y1-1));
		}
	}
	return 0;
}
/*
3 3
1 2 3
3 2 1
2 1 3
3
2 1 2 1 2 1
1 2 3 2
2 2 3 2 3 2
*/

  

posted @ 2017-08-27 18:57  zzd233  阅读(218)  评论(0编辑  收藏  举报