• [bzoj1452][JSOI2009]Count_树状数组


    Count bzoj-1452 JSOI-2009

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

    注释:$1le n,mle 300$,$1le 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
    ",query(x2,y2,val)+query(x1-1,y1-1,val)-query(x1-1,y2,val)-query(x2,y1-1,val));
    		}
    	}
    	return 0;
    }
    

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

  • 相关阅读:
    读《大道至简》第6章有感
    Java作业05(动手动脑)
    读《大道至简》第五章有感
    java作业04(动手动脑)
    域名与主机名
    STL 迭代器学习
    数组与链表增删改查效率比较
    智能指针多线程安全问题
    快速乘 学习
    关于TCP三个冗余ACK启动快速重传
  • 原文地址:https://www.cnblogs.com/ShuraK/p/9351848.html
Copyright © 2020-2023  润新知