目前想到两种解法,分别为O(n^3)和O(n^2~n^2*ln),python 7/20行以内搞定。

先说简单易理解的方法(7行)0:

  1. 取所有的矩形角点,对每个角点取所有矩形;
  2. 判断角点是否在矩形内,特别的,角点在边界上时只应当判断左半边。
n = int(input())
x1s, y1s = list(map(int, input().split())), list(map(int, input().split()))
x2s, y2s = list(map(int, input().split())), list(map(int, input().split()))

res = 1
for x in x1s+x2s:
    for y in y1s+y2s: # 取所有的矩形角点
        res = max(res, sum([x1s[i]<=x<x2s[i] and y1s[i]<=y<y2s[i] for i in range(n)])) # 对所有角点判断
print(res)

另外一种算法则会快很多:

核心想法是:如果存在重合,则某个矩形的右上角点必定比另一个矩形左下角的点靠近东北方。那么,我先压缩y维,只考虑x轴对所有点进行排序,判断x轴上的重复情况;然后再判断y轴上的重复情况。

  1. 那么,对每个点进行压栈排序:先从左到右排序点,当x坐标相同时优先排序右上角的点。【保证同一矩形左下角的点会先入列表,另一矩形同x位的左下角点会在之后,方便下方的stack进行操作】
  2. 遍历这个数组,会按x坐标的从小到大读出每一个点;对每一个点读出的点分别做以下判断,如果是左下角的点,入栈(实际上是个堆);否则进行以下算法:
  3. 对栈中的所有点按y的值大小进行排序,y值相同时优先排序右下角的点;按y值从小到大和右下角优先的规则读取整个栈,如果读到一个属于左下角的点,说明当前点(是一个右上角点)在其东北方,那么计数器加一;反之计数器减一。统计移动最高值。
  4. 把当前右上角点对应的左下角点移除出栈。
points = []
for x1, y1, x2, y2 in zip(x1s, y1s, x2s, y2s): # 对每个矩形
    points.append((x1, 1, y1, y2)); points.append((x2, -1, y1, y2))
points.sort() # 先按x的值排序靠左边的点 然后矩形右上角的点 然后排序y1 y2

stack, res = [], 1
for x, flag, y1, y2 in points: # 下一个出来的点一定在上一个的东方
    if flag == -1: # 是右上角的点
        cnt = 0; stack.sort() # 按高度y排序,此时堆里的点都是当前右上角点西边的矩阵的左下角点
        for _, f in stack:
            cnt += f; res = max(res, cnt)
        stack.remove((y1, 1)); stack.remove((y2, -1)) # 把当前右上角点对应的左下角点移除出栈
    else:
        stack.append((y1, 1)); stack.append((y2, -1))
print(res)