-
Notifications
You must be signed in to change notification settings - Fork 254
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
46 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
``` |