[POJ - 2029] Get Many Persimmon Trees (二维树状数组)

链接

http://poj.org/problem?id=2029

题意

给你一个 W × H W\times H W×H的公园,告诉你这个公园里栽有 n n n棵柿子树,并且告诉你这 n n n个柿子树的坐标,现在问你大小为 s × t s\times t s×t的土地上最多有多少棵柿子树;

分析

  二维线段树,把一维的树状数组,及插入函数 i n s e r t insert insert和求和函数 s u m sum sum均变成二维即可,每告诉一个柿子树坐标 ( x , y ) (x, y) (x,y),就在该位置插入一个1, s u m ( x , y ) sum(x, y) sum(x,y),即是求横坐标小于等于 x x x,纵坐标小于等于 y y y的那块区域的柿子树个数,所以我们枚举 s × t s\times t s×t的一个顶点,求出这块区域的柿子树个数,然后更新最大值即可,如果我们枚举给定区域最右下角的点,个数为 s u m ( x ,   y ) + s u m ( x − s ,   y − t ) − s u m ( x ,   y − t ) − s u m ( x − s ,   y ) sum(x,\ y) + sum(x - s,\ y - t) - sum(x,\ y - t) - sum(x - s,\ y) sum(x, y)+sum(xs, yt)sum(x, yt)sum(xs, y);最后还需要注意,对于0的 l o w b i t lowbit lowbit运算是无意义的;

代码
#include <functional>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <set>
#include <map>

#define INF 0x7f7f7f7f
#define MAXN 1000005
#define N 200005
#define P 2
#define MOD 99991

typedef long long ll;

namespace fastIO {
	//#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1<<22, stdin), p1 == p2) ? EOF : *p1++)
	//char buf[(1 << 22)], *p1 = buf, *p2 = buf;
	inline int read() {
		char c = getchar(); int x = 0, f = 1;
		while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); }
		while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
		return x * f;
	}
}

using namespace fastIO;
using namespace std;

int n, w, h, c[560][560];

void insert(int x, int y) {
	for (int i = x; i <= w; i += i & -i)
		for (int j = y; j <= h; j += j & -j)
			c[i][j] += 1;
}

int sum(int x, int y) {
	if (x <= 0 || y <= 0)return 0;
	int res = 0;
	for (int i = x; i > 0; i -= i & -i)
		for (int j = y; j > 0; j -= j & -j)
			res += c[i][j];
	return res;
}

int main() {
	while (cin >> n, n) {
		cin >> w >> h;
		int x, y;
		memset(c, 0, sizeof(c));
		for (int i = 1; i <= n; i++) {
			cin >> x >> y;
			insert(x, y);
		}
		cin >> x >> y;
		int maxm = 0;
		for (int i = x; i <= w; i++)
			for (int j = y; j <= h; j++) {
				int cnt = sum(i, j) + sum(i - x, j - y) - sum(i, j - y) - sum(i - x, j);
				maxm = max(maxm, cnt);
			}
		cout << maxm << endl;
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值