其他分享
首页 > 其他分享> > 题解 P4054 【[JSOI2009]计数问题】

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

作者:互联网

先无良宣传一下博客 \(wwwwww\)
文章列表 - 地灵殿 - 洛谷博客


知识点 : 多维树状数组 .

二维树状数组模板题 .

可以发现 , 矩阵中值的值域很小
\(w\le 100\)
考虑暴力思路,

构建 \(100\) 个二维树状数组,
分别存储各数值 ,
在矩阵中出现的次数.


另外 , \(bzoj\) 上的此题空间限制只有 \(64mb\)
要注意不能把所有变量,
都设置为 \(long\ long\) .


附 代码:

#include<cstdio>
#include<ctype.h>
#define ll long long
#define lowbit(x) -x&x
//=============================================================
int N,M,Q;
int map[301][301];
int tree[101][301][301];
//=============================================================
inline int read()
{
    int fl=1,w=0;char ch=getchar();
    while(!isdigit(ch) && ch!='-') ch=getchar();
    if(ch=='-') fl=-1;
    while(isdigit(ch)){w=w*10+ch-'0',ch=getchar();}
    return fl*w;
}
inline void add(int type,int x,int y,int z)//修改操作,将此点权值设为type,并使其次数+=z 
{
    map[x][y]=type;//更新 
    for(int i=x;i<=N;i+=lowbit(i))//进行拆分 
      for(int j=y;j<=M;j+=lowbit(j))
        tree[type][i][j]+=z;
}
inline ll sum(int type,int x,int y)//查询矩阵(1,1)--(x,y)中值type的出现次数 
{   
    int ret=0;
    for(int i=x;i;i-=lowbit(i))//进行拆分 
      for(int j=y;j;j-=lowbit(j))
        ret+=tree[type][i][j];//更新 
    return ret;
}
//=============================================================
signed main()
{
    N=read(),M=read();
    for(int i=1;i<=N;i++)
      for(int j=1;j<=M;j++)//构造初始树状数组 
      {
        int w=read();
        add(w,i,j,1);
      }
    
    Q=read();
    for(int i=0;i<Q;i++)
    {
      int opt=read();
      if(opt==1)//修改操作 
      {
        int x=read(),y=read(),type=read();
        add(map[x][y],x,y,-1);//原值出现次数-1 
        add(type,x,y,1);//新值出现次数+1 
      }
      else
      {
        int x1=read(),x2=read(),y1=read(),y2=read(),type=read();
        ll ans1=sum(type,x2,y2),ans2=sum(type,x1-1,y1-1);//计算子矩阵的值 
        printf("%lld\n",ans1-sum(type,x1-1,y2)-sum(type,x2,y1-1)+ans2);
      }
    }
}

标签:ch,树状,int,题解,JSOI2009,long,P4054,数组,301
来源: https://www.cnblogs.com/luckyblock/p/11456300.html