bzoj 1452 //1452:[JSOI2009] Count //[JSOI2009]计数问题 //在线测评地址https://www.lydsy.com/JudgeOnline/problem.php?id=1452
更多题解,详见https://blog.csdn.net/mrcrack/article/details/90228694BZOJ刷题记录
bzoj 1452
39340 kb | 6128 ms | C++/Edit | 1308 B |
洛谷2.75s / 38.41MB / 1.09KB C++
//1452:[JSOI2009] Count
//[JSOI2009]计数问题
//在线测评地址https://www.luogu.org/problem/P4054
//枚举算法也就30分,很好奇 二维树状数组 算法
//此文http://hzwer.com/3251.html代码写得不错,边看边画图,应该能很快看懂。
/*
发现第一次写二维树状数组
妈蛋就是多了一层for。。。
对于每种颜色开一个二维树状数组水过。。。
*/
//ans=ask(x2,y2,c)-ask(x1-1,y2,c)-ask(x2,y1-1,c)+ask(x1-1,y1-1,c);的理解详见下图
//编写过程中,树状数组update,ask写了两个奇杷的代码,如下,错误的
/*
void update(int x,int y,int c,int v){
while(x<=n){
while(y<=m){
C[x][y][c]+=v;
y+=lowbit(y);
}
x+=lowbit(x);
}
}
int ask(int x,int y,int c){
int ans=0;
while(x>0){
while(y>0){
ans+=C[x][y][c];
y-=lowbit(y);
}
x-=lowbit(x);
}
return ans;//漏了此句,查了10分钟
}
*/
//上述代码错误的原因在于y只在x的第一次循环起作用,之后,值就固定不变了。这个查了30分钟,才发现。
//样例通过,提交AC.2019-10-16 20:47
#include
#include
#define maxn 305
int n,m,map[maxn][maxn],C[maxn][maxn][105];//1<=c<=100
int lowbit(int x){
return x&-x;
}
void update(int x,int y,int c,int v){
int i,j;
for(i=x;i<=n;i+=lowbit(i))
for(j=y;j<=m;j+=lowbit(j))
C[i][j][c]+=v;
}
int ask(int x,int y,int c){
int ans=0,i,j;
for(i=x;i>0;i-=lowbit(i))
for(j=y;j>0;j-=lowbit(j))
ans+=C[i][j][c];
return ans;//漏了此句,查了10分钟
}
int main(){
int i,j,q,cmd,x1,y1,x2,y2,c,ans;
memset(C,0,sizeof(C));
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
scanf("%d",&map[i][j]),update(i,j,map[i][j],1);
scanf("%d",&q);
while(q--){
scanf("%d",&cmd);
if(cmd==1){
scanf("%d%d%d",&x1,&y1,&c);
update(x1,y1,map[x1][y1],-1);
map[x1][y1]=c;
update(x1,y1,map[x1][y1],1);
}
else if(cmd==2){
scanf("%d%d%d%d%d",&x1,&x2,&y1,&y2,&c);
ans=ask(x2,y2,c)-ask(x1-1,y2,c)-ask(x2,y1-1,c)+ask(x1-1,y1-1,c);
printf("%d\n",ans);
}
}
return 0;
}