JSOI2009 计数问题

把题面改下风格:

有 n*m 个点, 每个点 i 有权值 xi,yi,zi, 要求回答 q 次询问, 每次给定 l1, r1,l2, r2,l3,查询有多少点满足:

  1. l1 ≤ xi ≤ r1

  2. l2 ≤ yi ≤ r2

  3. l3 = zi


说是三维 log3 的查询, 但直接开 z 个二维树状数组, log 方也行。

#include<bits/stdc++.h>

using namespace std;

const int N = 303;

int n, m, a[N][N];
struct BIT {
	int t[N][N];
	BIT() {
		memset(t, 0, sizeof t);
	}
	void ins(int x, int y, int v) {
		int tmp = y;
		for(; x<=n; x+=(x&(-x))) {
			y = tmp;
			for(; y<=m; y+=(y&(-y)))
				t[x][y] += v;
		}
	}
	int ask_(int x, int y) {
		int res = 0, tmp = y;;
		for(; x; x-=(x&(-x))) {
			y = tmp;
			for(; y; y-=(y&(-y)))
				res += t[x][y];
		}
		return res;
	}
	int ask(int lx, int rx, int ly, int ry) {
		return ask_(rx, ry) - ask_(rx, ly-1) - ask_(lx-1, ry) + ask_(lx-1, ly-1);
	}
} T[103];

int main() {
	scanf("%d%d", &n, &m);
	for(int i=1; i<=n; ++i)
		for(int j=1; j<=m; ++j)
		{
			scanf("%d", &a[i][j]);
			T[a[i][j]].ins(i, j, 1);
		}
//	for(int i=1; i<=n; ++i, cout<<'
')
//		for(int j=1; j<=m; ++j) cout << T[a[i][j]].ask(i, i, j, j) << ' ';
//	cout << "# " << T[2].ask_(3, 3) << '
';
	int Q;
	scanf("%d", &Q);
	while(Q--)
	{
		int op;
		scanf("%d", &op);
		if(op == 1)
		{
			int x, y, c;
			scanf("%d%d%d", &x, &y, &c);
			T[a[x][y]].ins(x, y, -1);
			T[a[x][y] = c].ins(x, y, 1);
		}
		if(op == 2)
		{
			int lx, rx, ly, ry, c;
			scanf("%d%d%d%d%d", &lx, &rx, &ly, &ry, &c);
			cout << T[c].ask(lx, rx, ly, ry) << '
';
		}
	}
	return 0;
}
原文地址:https://www.cnblogs.com/tztqwq/p/14312444.html