目前想到两种解法,分别为O(n^3)和O(n^2~n^2*ln),python 7/20
行以内搞定。
先说简单易理解的方法(7行)0:
- 取所有的矩形角点,对每个角点取所有矩形;
- 判断角点是否在矩形内,特别的,角点在边界上时只应当判断左半边。
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轴上的重复情况。
- 那么,对每个点进行压栈排序:先从左到右排序点,当x坐标相同时优先排序右上角的点。【保证同一矩形左下角的点会先入列表,另一矩形同x位的左下角点会在之后,方便下方的stack进行操作】
- 遍历这个数组,会按x坐标的从小到大读出每一个点;对每一个点读出的点分别做以下判断,如果是左下角的点,入栈(实际上是个堆);否则进行以下算法:
- 对栈中的所有点按y的值大小进行排序,y值相同时优先排序右下角的点;按y值从小到大和右下角优先的规则读取整个栈,如果读到一个属于左下角的点,说明当前点(是一个右上角点)在其东北方,那么计数器加一;反之计数器减一。统计移动最高值。
- 把当前右上角点对应的左下角点移除出栈。
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)