2018山东冬令营:UPC 计数问题 (二维树状数组)
计数问题
时间限制: 1 Sec 内存限制: 128 MB提交: 185 解决: 51
[提交][状态][讨论版][命题人:admin]
题目描述
一个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)的个数。
接下来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
RMQ 查询问题;
m次查询 很且数量很大, 所以想到往树状数组上靠拢, 然后 这个地方又是 统计 x,y 的 那就时二维树状数组
但题意 又要 求 某个数的个数, 所以 tree【】【】【】 开到三维, C不到100 很ok
更新时, 先把 对应的位置上的数 全部-1 然后再把要变成的值+1 保证 全部变成, 并且更新节点
[code]
#include <iostream> #include <bits/stdc++.h> #include <string.h> #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; const int MOD=1e9+7; const int MAXN=1e5+15; const int INF=0x3f3f3f3f; typedef long long ll; inline ll qpow(ll x,ll n){ll res=1;for(;n;n>>=1){if(n&1)res=(res*x);x=(x*x);}return res;} const int N=305; int a[310][310]; int tree[305][305][105]; int n,m; int lowbit(int x) { return x&(-x); } void update(int x,int y,int c,int k ) { int i, j; for(i=x;i<=m;i+=lowbit(i)) { for(j=y; j<=n; j+=lowbit(j)) { tree[i][j][c] += k; } } } int Sum( int x, int y ,int c) { int res=0,i,j; for(i=x;i>0;i-=lowbit(i)) { for(j=y; j>0; j-=lowbit(j)) { res += tree[i][j][c]; } } return res; } int main() { scanf("%d %d",&n,&m); int sum=0; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { scanf("%d",&a[i][j]); update(i,j,a[i][j],1); } } int q; scanf("%d",&q); while(q--) { int f; scanf("%d",&f); if(f==1) { int x,y,z; scanf("%d %d %d",&x,&y,&z); update(x,y,a[x][y],-1); update(x,y,z,1); a[x][y]=z; } else { int x1,x2,y1,y2,z; scanf("%d %d %d %d %d",&x1,&x2,&y1,&y2,&z); int sum= Sum(x2,y2,z)-Sum(x2,y1-1,z)-Sum(x1-1,y2,z)+Sum(x1-1,y1-1,z); printf("%d\n",sum); } } return 0; }
123
岂曰无衣?与子同袍。王于兴师,修我戈矛。与子同仇!
岂曰无衣?与子同泽。王于兴师,修我矛戟。与子偕作!
岂曰无衣?与子同裳。王于兴师,修我甲兵。与子偕行!