其他分享
首页 > 其他分享> > USACO2020DEC第五题(Rectangular Pasture)题解

USACO2020DEC第五题(Rectangular Pasture)题解

作者:互联网

题目
题目描述
Farmer John 最大的牧草地可以被看作是一个由方格组成的巨大的二维方阵(想象一个巨大的棋盘)。现在,有 N 头奶牛正占据某些方格(1≤N≤2500)。
Farmer John 想要建造一个可以包围一块矩形区域的栅栏;这个矩形必须四边与 x 轴和 y 轴平行,最少包含一个方格。请帮助他求出他可以包围在这样的区域内的不同的奶牛子集的数量。注意空集应当被计算为答案之一。
输入格式
输入的第一行包含一个整数 N。以下 N 行每行包含两个空格分隔的整数,表示一头奶牛所在方格的坐标 (x,y)。所有 x 坐标各不相同,所有 y 坐标各不相同。所有 x 与 y 的值均在 0…10^9 范围内。
输出格式
输出 FJ 可以包围的奶牛的子集数量。可以证明这个数量可以用 64 位有符号整数型存储(例如 C/C++ 中的long long)。
输入输出样例
输入 #1
4
0 2
1 0
2 3
3 5
输出 #1
13
说明/提示
共有 2^4 个子集。FJ 不能建造一个栅栏仅包围奶牛 1、2、4,或仅包围奶牛 2、4,或仅包围奶牛 1、4,所以答案为 2^4−3=16−3=132
测试点 2-3 满足 N≤20。
测试点 4-6 满足 N≤100。
测试点 7-12 满足 N≤500。
测试点 13-20 没有额外限制。
解题思路
我们先把整张地图压缩到n*n,类似8皇后的地图(每行每列只有一个点)。
这里我们用二维的前缀和来维护一块区域内的奶牛数。
无论矩形长什么样,只要围住相同的牛就是一样的,考虑最小的矩形即可
所以矩形的边上一定有一头奶牛。我们先枚举矩形上下两条边,然后看左右两边。假设我们将奶牛a=(xa,ya)和b=(xb,yb)固定在矩形的上下两侧,那么矩形左边的牛c必须满足xc≤min(xa,xb)和ya≤yc≤yb。
换句话说,c的可能数量是矩形内的点的数量[1,min(xa,xb)]×[ya,yb],而d的可能数量是矩形内的奶牛数量[max(xa,xb),n]×[ya,yb]。我们可以用二维前缀和来计算这些量。
参考代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2505;
int a[N], b[N];
int n;
struct node {
	int x, y;
} pos[N];
int sum[N][N];
bool cmp(node x, node y) {
	return x.y < y.y;
}
int get(int x1, int y1, int x2, int y2) {
	return sum[x2][y2] - sum[x2][y1 - 1] - sum[x1 - 1][y2] + sum[x1 - 1][y1 - 1];
}
int main() {
	cin >> n;
	for (int i = 1; i <= n; ++i) {
		cin >> pos[i].x >> pos[i].y;
		a[i] = pos[i].x; b[i] = pos[i].y;
	}
	sort(a + 1, a + n + 1); sort(b + 1, b + n + 1);
	for (int i = 1; i <= n; ++i) {
		pos[i].x = lower_bound(a + 1, a + n + 1, pos[i].x) - a;
		pos[i].y = lower_bound(b + 1, b + n + 1, pos[i].y) - b;
		sum[pos[i].x][pos[i].y] = 1;
	}
	sort(pos + 1, pos + n + 1, cmp);
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= n; ++j) {
			sum[i][j] += sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1];
		}
	}
	ll ans = 0;
	for (int i = 1; i <= n; ++i) {
		for (int j = i; j <= n; ++j) {
			int tmp1 = min(pos[i].x, pos[j].x);
            int tmp2 = max(pos[i].x, pos[j].x);
			ans += get(1, pos[i].y, tmp1, pos[j].y) * get(tmp2, pos[i].y, n, pos[j].y);
		}
	}
	cout << ans + 1 << '\n';
	return 0;
}

标签:矩形,测试点,int,题解,sum,pos,USACO2020DEC,Pasture,奶牛
来源: https://blog.csdn.net/yueyuedog/article/details/112426920