这个洛谷怎么对于python不太友好呢,没几次能全过的
本题使用扫描线的模板,首先把所有x坐标排序去重,放进列表X中。把所有横线lines排序。这样把所有矩阵都分成了块。对于每一块,高=lines[i+1]-lines[i],宽就等于在这一块中,每个矩阵的并。
比如说图中,纵坐标在3-5之间,那么高度就是2,其中有两块矩阵并起来,计算并起来的宽度=80-10=70,高×宽就是这一块的面积。
所有块的面积之和就是ans。
class node:
def __init__(self, l = None, r = None, cnt = 0, len = 0):
self.l = l
self.r = r
self.cnt = cnt
self.len = len
def build(idx, l, r):
tr[idx] = node(l, r, 0, 0)
if l == r: return
mid = l + r >> 1
build(2*idx, l, mid)
build(2*idx+1, mid+1, r)
def dich(num):
l, r = 0, length-1
while l < r:
mid = l + r >> 1
if X[mid] < num:
l = mid + 1
else:
r = mid
return l
def pushup(idx):
if tr[idx].cnt:
tr[idx].len = X[tr[idx].r+1] - X[tr[idx].l]
else:
try:
tr[idx].len = tr[2*idx].len + tr[2*idx+1].len
except:
tr[idx].len = 0
def modify(idx, l, r, tag):
if tr[idx].l > r or tr[idx].r < l: return
elif l <= tr[idx].l and tr[idx].r <= r:
tr[idx].cnt += tag
pushup(idx)
return
modify(2*idx, l, r, tag)
modify(2*idx+1, l, r, tag)
pushup(idx)
n = int(input())
X = [-float('inf')]
lines = []
# tr中存放所有节点的,l, r, cnt覆盖次数, len覆盖长度
tr = [node()]*(8*n)
ans = 0
for i in range(n):
x1, y1, x2, y2 = map(int, input().split())
X.append(x1)
X.append(x2)
lines.append([y1, x1, x2, 1])
lines.append([y2, x1, x2, -1])
X = sorted(list(set(X)))
length = len(X)
lines.sort()
build(1, 1, length-2)
# 扫描开始
for i in range(len(lines)-1):
y, x1, x2, tag = lines[i]
l = dich(x1)
r = dich(x2)-1
modify(1, l, r, tag)
ans += tr[1].len*(lines[i+1][0] - lines[i][0])
print(ans)
其中需要注意的是,把X排完序,想要从坐标1开始计算,那在X最前面加一个-inf,保证排序从1开始。
又发现X是离散的,所以需要离散化
这样线段树的就以下标为值,例如根节点就是1-5。那么有人就会问为什么不是1-6呢?
如果是1-6,它的左节点就是1-4,右节点就是5-6,我们发现从4到5,实际上差了20,显然不可行。
我们让右左标偏移。
这样右边的5就代表90,左边的1还是代表10。