2 条题解

  • 0
    @ 2025-12-3 18:31:53
    • 现将横坐标离散化,这样 xi,yi1000x_i, y_i \le 1000
    • 我们就可以用一个 1000×10001000 \times 1000 的二维数组来记录所有点
    • 然后再枚举所有的水平线和竖直线
    • 此时不用再枚举所有的点,用 二维前缀和 就可以 O(1)O(1) 的计算出每个区域的点数
    • 时间复杂度:O(n2)O(n^2)
    #include <bits/stdc++.h>
    using namespace std;
    
    using pii = pair<int, int>;
    
    int main() {
    	ios::sync_with_stdio(false);
    	cin.tie(0); cout.tie(0);
    
    	int n;
        cin >> n;
        vector<int> x(n), y(n), px(n), py(n);
        for (int i = 0; i < n; i++) {
            cin >> x[i] >> y[i];
            px[i] = x[i], py[i] = y[i];
        }
    
        // 离散化
        sort(x.begin(), x.end());                      // 排序
        x.erase(unique(x.begin(), x.end()), x.end());  // 去重
        int ex = x.size();
        for (int i = 0; i < n; i++) {
            px[i] = lower_bound(x.begin(), x.end(), px[i]) - x.begin() + 1;
        }
    
        // 离散化
        sort(y.begin(), y.end());                      // 排序
        y.erase(unique(y.begin(), y.end()), y.end());  // 去重
        int ey = y.size();
        for (int i = 0; i < n; i++) {
            py[i] = lower_bound(y.begin(), y.end(), py[i]) - y.begin() + 1;
        }
    
        // 二维前缀和
        vector<vector<int>> f(ex + 1, vector<int>(ey + 1, 0));
        for (int i = 0; i < n; i++) f[px[i]][py[i]] = 1;
        for (int i = 1; i <= ex; i++) for (int j = 1; j <= ey; j++) {
            f[i][j] = f[i - 1][j] + f[i][j - 1] - f[i - 1][j - 1] + f[i][j];
        }
    
        // 计算 [x1, y1] 到 [x2, y2] 形成的矩形的和
        auto cal = [&](int x1, int y1, int x2, int y2) -> int {
            return f[x2][y2] - f[x2][y1 - 1] - f[x1 - 1][y2] + f[x1 - 1][y1 - 1];
        };
    
        // 枚举 水平线 和 竖直线
        int ans = n;
        for (int i = 1; i < ex; i++) for (int j = 1; j < ey; j++) {
            int c1 = cal(1, 1, i, j);            // 左上
            int c2 = cal(i + 1, 1, ex, j);       // 左下
            int c3 = cal(1, j + 1, i, ey);       // 右上
            int c4 = cal(i + 1, j + 1, ex, ey);  // 右下
            ans = min(ans, max({c1, c2, c3, c4}));
        }
        cout << ans << '\n';
    
    	return 0;
    }
    
    • 0
      @ 2025-12-3 18:29:11
      • 先枚举所有可能的水平线和竖直线
      • 再枚举所有点的,看看在哪个区域
      • 时间复杂度:O(n3)O(n^3)
      • 期望得分:5050
      #include <bits/stdc++.h>
      using namespace std;
      
      using pii = pair<int, int>;
      
      int main() {
      	ios::sync_with_stdio(false);
      	cin.tie(0); cout.tie(0);
      
      	int n;
          cin >> n;
          vector<int> x(n), y(n);
          for (int i = 0; i < n; i++) {
              cin >> x[i] >> y[i];
          }
      
          // 枚举 水平线 和 竖直线
          int ans = n;
          for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {
      
              int a = x[i], b = y[j];  // 水平线, 竖直线
              int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
      
              for (int k = 0; k < n; k++) {
                  int u = x[k], v = y[k];
      
                  if (u <= a && v <= b) c1++;  // 左上
                  if (u >  a && v <= b) c2++;  // 左下
                  if (u <= a && v >  b) c3++;  // 右上
                  if (u >  a && v >  b) c4++;  // 右下
              }        
              ans = min(ans, max({c1, c2, c3, c4}));
          }
          cout << ans << '\n';
      
      	return 0;
      }
      
      • 1

      信息

      ID
      206
      时间
      100ms
      内存
      32MiB
      难度
      7
      标签
      递交数
      20
      已通过
      8
      上传者