Skip to content

Commit

Permalink
Editorial for CF822C
Browse files Browse the repository at this point in the history
  • Loading branch information
Yawn-Sean committed Apr 6, 2024
1 parent ae2a26e commit bc35a78
Showing 1 changed file with 46 additions and 0 deletions.
46 changes: 46 additions & 0 deletions daily_problems/2024/04/0406/solution/cf822c.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
**提示 1:** 我们选取区间的顺序不重要,因此可以钦定第一个区间在第二个区间左边。

**提示 2:** 尝试固定一个区间,则另一个区间应当满足什么条件?能否设计方法快速找到满足条件的最优区间?

首先,由提示 1,不妨设第一个区间在第二个区间左边。那么第二个区间的左端点一定在第一个区间的右端点右侧。

这时,我们固定第一个区间,则第二个区间只需要满足上述条件,且长度与选取的第一个区间的长度和为 $x$ 即可。

而如果我们将区间关于左端点排序,这些区间恰好构成后缀,我们只在意这个后缀中,长度为 $k$ 的区间的最小成本。

因此,我们按照右端点从大到小的顺序遍历区间,则其对应的后缀越来越长,我们只需要添加区间加入后缀即可。

而添加区间时,某一长度线段的最小成本的维护是很容易的,再找到与左侧枚举的区间长度和为 $x$ 的结果进行结果的更新即可。因此完全遍历后即可得到答案。

时间复杂度为 $\mathcal{O}(n+M)$ ,如果直接使用值域比较小的条件的话。

#### 具体代码如下(只包含中间处理部分)——

```Python []
def main():
n, x = MII()
# 其实不建议这么写,直接开列表存下所有区间表现应当更好一些
left = [Counter() for _ in range(2 * 10 ** 5 + 1)]
right = [Counter() for _ in range(2 * 10 ** 5 + 1)]

for _ in range(n):
l, r, c = MII()
if r - l + 1 not in left[l] or left[l][r-l+1] > c:
left[l][r-l+1] = c
if r - l + 1 not in right[r] or right[r][r-l+1] > c:
right[r][r-l+1] = c

ans = inf
cur = Counter()
for i in range(2 * 10 ** 5):

for v in right[i]:
if v not in cur or cur[v] > right[i][v]:
cur[v] = right[i][v]

for v in left[i+1]:
if x - v in cur:
ans = min(ans, cur[x-v] + left[i+1][v])

print(ans if ans < inf else -1)
```

0 comments on commit bc35a78

Please sign in to comment.