NOIP2020 做题练习(day3)

A - 金牌赛事

题面

Codeforces 原题

首先设 \(dp_i\) 表示考虑前 \(i\) 条道路的最大利润。

转移:\(dp_i=\max\{dp_{i-1}, \max\limits_{j=0}^{i-1}\{dp_j-s(j+1,i)+w(j+1,i)\}\}\)

其中 \(s(j+1,i)\) 表示修理道路 \([j+1,i]\) 的费用之和,即 \(\sum\limits_{k=j+1}^i c_k\)\(w(j+1,i)\) 表示道路 \([j+1,i]\) 所有赛事的利润之和。

后面的式子可以用线段树维护,具体就是每一个节点 \(i\) 维护 \(dp_i-c_i+\)\(i\) 为终点的赛事利润之和。

右端点每次位移就相当于进行区间修改操作。

代码

B - 公园晨跑

题面

Codeforces 原题

把边的贡献转移到点上,断环成链,然后又变成了一个区间查询的线段树。

注意特判选择两个点重合的情况,这个时候就需要固定一个端点后取最大值。

代码

C - 幸运树

题面

Codeforces 原题

容斥之后直接并查集算答案,注意别算重。

代码

D - 一堆的堆

题面

Codeforces 原题

注意到 \(i\) 叉堆点 \(j\) 的儿子范围是 \([j\times i-i+2,j\times i+1]\),那么可以先对整个序列排序,再用一个树状数组维护不合法节点数量。复杂度为调和级数。

代码

E - 赛道修建

题面

首先二分答案。

然后在 dfs 的过程中,每次传上来一条以儿子节点为头的最长链,用一个 multiset 从小到大匹配。

注意二分上界要调到树的直径才能过。

代码

posted @ 2020-09-19 22:29  csxsi  阅读(177)  评论(0编辑  收藏  举报