[bzoj1452][JSOI2009]Count_树状数组

Count bzoj-1452 JSOI-2009

题目大意:请维护一个平面内的数据结构,支持:单点修改,查询矩形内给定权值出现次数。

注释:$1\le n,m\le 300$,$1\le Q \le 5000$,n和m分别是长和宽,Q是操作次数。

想法:显然,我们根据权值线段树,给这种数据结构起个名字... ...

二维权值树状数组。

我们对树状数组上的节点开一个桶,Tree[i][j][val]表示再以(i,j)右下端点、以(1,1)为左上端点的矩阵中权值为val的数的个数。

对于每个修改直接在对应权值上修改,查询向前查询即可。

最后,附上丑陋的代码... ...

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int tree[310][310][110],a[310][310],n,m;
inline int lowbit(int x){return x&(-x);}
void fix(int x,int y,int val,int flag)
{
	for(int i=x;i<=(n);i+=lowbit(i))
	{
		for(int j=y;j<=(m);j+=lowbit(j))
		{
			tree[i][j][val]+=flag;
		}
	}
}
int query(int x,int y,int val)
{
	int ans=0;
	for(int i=x;i;i-=lowbit(i))
	{
		for(int j=y;j;j-=lowbit(j))
		{
			ans+=tree[i][j][val];
		}
	}
	return ans;
}
int main()
{
	cin >> n >> m ;
	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++)
	{
		scanf("%d",&a[i][j]);
		fix(i,j,a[i][j],1);
	}
	int q,opt,x1,x2,y1,y2,x,y,val; cin >> q ;
	while(q--)
	{
		scanf("%d",&opt);
		if(opt==1)
		{
			scanf("%d%d%d",&x,&y,&val);
			fix(x,y,a[x][y],-1);
			a[x][y]=val;
			fix(x,y,a[x][y],1);
		}
		else
		{
			scanf("%d%d%d%d%d",&x1,&x2,&y1,&y2,&val);
			printf("%d\n",query(x2,y2,val)+query(x1-1,y1-1,val)-query(x1-1,y2,val)-query(x2,y1-1,val));
		}
	}
	return 0;
}

 小结:树状数组是真tm好写... ...

posted @ 2018-07-22 22:45  JZYshuraK_彧  阅读(148)  评论(0编辑  收藏  举报