Farmer John's largest pasture can be regarded as a large 2D grid of square "cells" (picture a huge chess board). Currently, there are NN cows occupying some of these cells (1≤N≤25001≤N≤2500).
Farmer John wants to build a fence that will enclose a rectangular region of cells; the rectangle must be oriented so its sides are parallel with the xx and yy axes, and it could be as small as a single cell. Please help him count the number of distinct subsets of cows that he can enclose in such a region. Note that the empty subset should be counted as one of these.
The first line contains a single integer NN. Each of the next NN lines Each of the next NN lines contains two space-separated integers, indicating the (x,y)(x,y) coordinates of a cow's cell. All xx coordinates are distinct from each-other, and all yy coordinates are distinct from each-other. All xx and yy values lie in the range 0…1090…109.
The number of subsets of cows that FJ can fence off. It can be shown that this quantity fits within a signed 64-bit integer (e.g., a "long long" in C/C++).
4 0 2 1 0 2 3 3 5
13
There are 2424 subsets in total. FJ cannot create a fence enclosing only cows 1, 2, and 4, or only cows 2 and 4, or only cows 1 and 4, so the answer is 24−3=16−3=1324−3=16−3=13.
Problem credits: Benjamin Qi
[/hide]
(Analysis by Benjamin Qi)
First, compress all of the xx and yy coordinates so that everything is in the range [0,N−1][0,N−1].
For each nonempty subset of cows that can be fenced off, consider the rectangle of the minimum size that encloses the subset. This rectangle must contain a cow on each of its four sides. Conversely, each rectangle with a cow on each of its sides corresponds to a unique subset of cows that can be fenced off. Due to the condition that all coordinates are distinct, each side will contain exactly one cow.
A naive approach would be to test whether each of the O(N4)O(N4) possible rectangles satisfies this condition, giving an O(N5)O(N5) time solution. For additional an O(N4)O(N4) time solution, check each rectangle in O(1)O(1) time.
For full credit, we need an O(N2)O(N2) solution. Suppose that we fix the cows a=(xa,ya)a=(xa,ya) and b=(xb,yb)b=(xb,yb) on the bottom and top sides of the rectangle (so ya≤ybya≤yb). Then the cow cc on the left side of the rectangle must satisfy xc≤min(xa,xb)xc≤min(xa,xb) and ya≤yc≤ybya≤yc≤yb. Similarly, the cow dd on the right side of the rectangle must satisfy max(xa,xb)≤xdmax(xa,xb)≤xd and ya≤yd≤ybya≤yd≤yb. In other words, the number of possibilities for cc is the number of points in the rectangle [0,min(xa,xb)]×[ya,yb][0,min(xa,xb)]×[ya,yb] while the number of possibilities for dd is the number of cows in the rectangle [max(xa,xb),N−1]×[ya,yb][max(xa,xb),N−1]×[ya,yb]. We can compute these quantities using 2D prefix sums.
Brian Dean's code:
#include <iostream> #include <algorithm> using namespace std; typedef pair<int,int> Point; bool ycomp(Point p, Point q) { return p.second < q.second; } const int MAX_N = 2500; int N, Psum[MAX_N+1][MAX_N+1]; Point P[MAX_N]; int rsum(int x1, int y1, int x2, int y2) { return Psum[x2+1][y2+1] - Psum[x2+1][y1] - Psum[x1][y2+1] + Psum[x1][y1]; } int main(void) { cin >> N; for (int i=0; i<N; i++) { int x, y; cin >> x >> y; P[i] = make_pair(x,y); } sort(P, P+N); for (int i=0; i<N; i++) P[i].first = i+1; sort(P, P+N, ycomp); for (int i=0; i<N; i++) P[i].second = i+1; for (int i=0; i<N; i++) Psum[P[i].first][P[i].second] = 1; for (int i=1; i<=N; i++) for (int j=1; j<=N; j++) Psum[i][j] += Psum[i-1][j] + Psum[i][j-1] - Psum[i-1][j-1]; long long answer = 0; for (int i=0; i<N; i++) for (int j=i; j<N; j++) { int x1 = min(P[i].first, P[j].first) - 1; int x2 = max(P[i].first, P[j].first) - 1; answer += rsum(0,i,x1,j) * rsum(x2,i,N-1,j); } cout << answer + 1 << "\n"; }
Danny Mittal's code:
import java.util.Arrays; import java.util.Comparator; import java.util.Scanner; public class RectangularPasture { static int[][] sums; static int getSum(int fromX, int toX, int fromY, int toY) { return sums[toX][toY] - sums[fromX - 1][toY] - sums[toX][fromY - 1] + sums[fromX - 1][fromY - 1]; } public static void main(String[] args) { Scanner in = new Scanner(System.in); int n = in.nextInt(); int[] xs = new int[n]; int[] ys = new int[n]; Integer[] cows = new Integer[n]; for (int j = 0; j < n; j++) { xs[j] = in.nextInt(); ys[j] = in.nextInt(); cows[j] = j; } Arrays.sort(cows, Comparator.comparingInt(j -> xs[j])); for (int x = 1; x <= n; x++) { xs[cows[x - 1]] = x; } Arrays.sort(cows, Comparator.comparingInt(j -> ys[j])); for (int y = 1; y <= n; y++) { ys[cows[y - 1]] = y; } sums = new int[n + 1][n + 1]; for (int j = 0; j < n; j++) { sums[xs[j]][ys[j]]++; } for (int x = 0; x <= n; x++) { for (int y = 0; y <= n; y++) { if (x > 0) { sums[x][y] += sums[x - 1][y]; } if (y > 0) { sums[x][y] += sums[x][y - 1]; } if (x > 0 && y > 0) { sums[x][y] -= sums[x - 1][y - 1]; } } } long answer = n + 1; for (int j = 0; j < n; j++) { for (int k = j + 1; k < n; k++) { answer += getSum(Math.min(xs[j], xs[k]), Math.max(xs[j], xs[k]), 1, Math.min(ys[j], ys[k])) * getSum(Math.min(xs[j], xs[k]), Math.max(xs[j], xs[k]), Math.max(ys[j], ys[k]), n); } } System.out.println(answer); } }
[/hide]
翰林课程体验,退费流程快速投诉邮箱: yuxi@linstitute.net 沪ICP备2023009024号-1