[JSOI2009]计数问题 二维树状数组BZOJ 1452
题目描述
一个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,按照在输入中出现的顺序,依次输出一行一个整数表示所求得的个数。
输入输出样例
说明
数据规模:30%的数据,满足:n,m<=30,Q<=50000
#include<iostream> #include<cstdio> #include<algorithm> #include<cstdlib> #include<cstring> #include<string> #include<cmath> #include<map> #include<set> #include<vector> #include<queue> #include<bitset> #include<ctime> #include<deque> #include<stack> #include<functional> #include<sstream> //#include<cctype> //#pragma GCC optimize(2) using namespace std; #define maxn 200005 #define inf 0x7fffffff //#define INF 1e18 #define rdint(x) scanf("%d",&x) #define rdllt(x) scanf("%lld",&x) #define rdult(x) scanf("%lu",&x) #define rdlf(x) scanf("%lf",&x) #define rdstr(x) scanf("%s",x) typedef long long ll; typedef unsigned long long ull; typedef unsigned int U; #define ms(x) memset((x),0,sizeof(x)) const long long int mod = 1e9; #define Mod 1000000000 #define sq(x) (x)*(x) #define eps 1e-5 typedef pair<int, int> pii; #define pi acos(-1.0) //const int N = 1005; #define REP(i,n) for(int i=0;i<(n);i++) typedef pair<int, int> pii; inline int rd() { int x = 0; char c = getchar(); bool f = false; while (!isdigit(c)) { if (c == '-') f = true; c = getchar(); } while (isdigit(c)) { x = (x << 1) + (x << 3) + (c ^ 48); c = getchar(); } return f ? -x : x; } ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a%b); } int sqr(int x) { return x * x; } /*ll ans; ll exgcd(ll a, ll b, ll &x, ll &y) { if (!b) { x = 1; y = 0; return a; } ans = exgcd(b, a%b, x, y); ll t = x; x = y; y = t - a / b * y; return ans; } */ int c[302][310][310]; int a[500][500]; int n, m; void add(int x, int y,int val,int col) { for (int i = x; i <= n; i += i & -i) { for (int j = y; j <= m; j += j & -j) { c[col][i][j] += val; } } } int query(int x, int y, int col) { int ans = 0; for (int i = x; i > 0; i -= i & -i) { for (int j = y; j > 0; j -= j & -j) { ans += c[col][i][j]; } } return ans; } int main() { //ios::sync_with_stdio(0); n = rd(); m = rd(); for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++)a[i][j] = rd(), add(i, j, 1, a[i][j]); } int q; q = rd(); while (q--) { int opt; opt = rd(); if (opt == 1) { int x, y, c; x = rd(); y = rd(); c = rd(); add(x, y, -1, a[x][y]); a[x][y] = c; add(x, y, 1, a[x][y]); } else { int a, x, b, y; a = rd(); x = rd(); b = rd(); y = rd(); int c; c = rd(); int ans = query(x, y, c) - query(a - 1, y, c) - query(x, b - 1, c) + query(a - 1, b - 1, c); printf("%d\n", ans); } } return 0; }
EPFL - Fighting