zoukankan      html  css  js  c++  java
  • [二维树状数组]计数问题

    题目描述

     一个n*m的方格,初始时每个格子有一个整数权值。接下来每次有2种操作:
    改变一个格子的权值;
    求一个子矩阵中某种特定权值出现的个数。

    输入

    第一行有两个数n,m。
    接下来n行,每行m个数,第i+1行第j个数表示格子(i,j)的初始权值。
    接下来输入一个整数q。
    接下来q行,每行描述一个操作。
    操作1:“1 x y c”(不含双引号)。表示将格子(x,y)的权值改成c(1<=x<=n,1<=y<=m,1<=c<=100)。
    操作2:“2 x1 x2 y1 y2 c”(不含双引号,x1<=x2,y1<=y2)。表示询问所有满足格子权值为c,且x1<=x<=x2,y1<=y<=y2的格子(x,y)的个数。

    输出

    对于每个操作2,按照在输入中出现的顺序,依次输出一行一个整数表示所求得的个数。

    样例输入

    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
    

    样例输出

    1
    2
    

    提示

    对于30%的数据n,m<=30,q<=10000
    对于100%的数据 n,m<=300,q<=100000,1<=c<=100

    思路:求询问区间内某一个值出现的次数;
    单点更新:若在某个位置(i,j)出现了某个数k则标记为1(三位数组c[i][j][k]记录这个信息),原先的数标记为0;
    区间求和:求区间内某个数k出现次数即调用getsum(i,j,k)求和c[..][..][k]数组得到(1,1)-(i,j)内k出现的次数;结果是getsum(xx,yy,k)-getsum(xx,y-1,k)-getsum(x-1,yy,k)+getsum(x-1,y-1,k);(容斥原理)
    AC代码:
    #include <iostream>
    #include<cstdio>
    #define lowbit(x) x&(-x)
    using namespace std;
    
    int n,m;
    int Map[310][310];
    int c[310][310][110];
    
    void add(int x,int y,int k,int val){
       for(int i=x;i<=n;i+=lowbit(i)){
         for(int j=y;j<=m;j+=lowbit(j)){
            c[i][j][k]+=val;
         }
       }
    }
    
    int getsum(int x,int y,int k){
       int ret=0;
       for(int i=x;i>0;i-=lowbit(i)){
         for(int j=y;j>0;j-=lowbit(j)){
            ret+=c[i][j][k];
         }
       }
       return ret;
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                scanf("%d",&Map[i][j]);
                add(i,j,Map[i][j],1);
            }
        }
        int q;
        scanf("%d",&q);
        while(q--){
            int op;
            scanf("%d",&op);
            if(op==1){
                int x,y,k;
                scanf("%d%d%d",&x,&y,&k);
                add(x,y,Map[x][y],-1);
                add(x,y,k,1);
                Map[x][y]=k;
            }
            if(op==2){
                int x,xx,y,yy,k;
                scanf("%d%d%d%d%d",&x,&xx,&y,&yy,&k);
                printf("%d
    ",getsum(xx,yy,k)-getsum(x-1,yy,k)-getsum(xx,y-1,k)+getsum(x-1,y-1,k));
            }
        }
        return 0;
    }
     
    转载请注明出处:https://www.cnblogs.com/lllxq/
  • 相关阅读:
    gojs入门
    chartjs:改变图表的外观
    chart.js入门
    verilog与C语言的6点重大区别
    PCB布线原则【转】_神经火光_百度空间
    verilog中对同一个变量有判断条件的赋值
    同步复位与异步复位——异步复位同步释放
    如何利用TCL文件给FPGA分配引脚
    0欧姆电阻的作用
    独热码
  • 原文地址:https://www.cnblogs.com/lllxq/p/9095555.html
Copyright © 2011-2022 走看看