• 【题解】[JSOI2009]计数问题


    Problem

    ( ext{Solution:})

    开始有一种暴力的做法:对每一行维护 (100) 个树状数组对应 (100) 个颜色。查询枚举行来查询。

    复杂度:(O(mcdot log ncdot q)) 过不去的样子。

    考虑用二维树状数组,直接维护二维矩阵。修改与查询的复杂度都做到了 (O(log ncdot log m).)

    于是最终复杂度可以做到 (O(qlog nlog m).)

    注意树状数组实现上的细节:第二重循环要保证每次都是从 (y) 开始,所以要重新复制一个变量来做。而且两个维度的最大值也是不一样的,上界不同修改的时候要注意。

    这题的树状数组显然没有 上帝造题的七分钟 那个树状数组难。这题算是入门版的二维树状数组。

    维护矩阵同时维护一个颜色即可

    #include<bits/stdc++.h>
    using namespace std;
    int tr[301][301][101],n,m,a[301][301],q;
    inline int lowbit(int x){return x&(-x);}
    void change(int x,int y,int c,int v){
    	for(;x<=n;x+=lowbit(x))
    		for(int i=y;i<=m;i+=lowbit(i))
    			tr[x][i][c]+=v;
    }
    int query(int x,int y,int c){
    	int res=0;
    	for(;x;x-=lowbit(x))
    		for(int i=y;i;i-=lowbit(i))
    			res+=tr[x][i][c];
    	return res;
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;++i)
    		for(int j=1;j<=m;++j){
    			scanf("%d",&a[i][j]);
    			change(i,j,a[i][j],1);
    		}
    	scanf("%d",&q);
    	for(;q;q--){
    		int opt;
    		scanf("%d",&opt);
    		if(opt==1){
    			int x,y,c;
    			scanf("%d%d%d",&x,&y,&c);
    			change(x,y,a[x][y],-1);
    			a[x][y]=c;
    			change(x,y,a[x][y],1);
    		}
    		else{
    			int ax,bx,ay,by,c;
    			scanf("%d%d%d%d%d",&ax,&bx,&ay,&by,&c);
    			int ans=query(bx,by,c)-query(ax-1,by,c)-query(bx,ay-1,c)+query(ax-1,ay-1,c);
    			printf("%d
    ",ans);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    应用实例:用户登录(2009.10.23)
    ASP.NET学习笔记:服务器控件 (2009.11.9)
    小实例:模拟电话簿
    用Iframe实现左边TreeView导航,右边显示相应内容的布局
    HTML&CSS&JaveScript学习笔记(2009.11.19)
    C#中问号(?)的用法
    GridView的简单分页等
    GridView正反双向排序
    代码理解(2009.11.20)
    ASP.NET学习笔记:数据库操作 (2009.11.10)
  • 原文地址:https://www.cnblogs.com/h-lka/p/14944571.html
Copyright © 2020-2023  润新知