2019.12.07【NOIP提高组】模拟A 组总结

220分,不错,但还是有很大的提升空间。

本来可以250的。

T1

最大最小值的问题就想到二分答案。

然后可以枚举三刀,最后问题就转化为能否再切三刀使得每一块的和大于等于mid,那么直接单调往下切即可。

T2:

暴力dp,没有太多想法。

设f[i][0/1]表示走完所有 i 这个点中子树的规定点后走不走回来的答案。

转移:f[i][0]=sum{f[son][0]+len}

f[i][1]=min{f[x][0],f[i][0]-len-f[son][0]+f[son][1]};

时间O(n^2)

考虑换根。

可以理解为将所有点走一遍后减去当前点到关键点中最远的点的距离(设为sum-max)。

分类讨论。

x(father)->y(son)时,len为边长

1.x往上以及y往下都有要经过的点。、

      sum'=sum

      如果x的最长链经过y,则y的最长链=max(x的次长链+len,y的最长链)。

      否则,y的最长链=max(x的最长链+len,y的最长链)。

2.如果x上有y下面没有 

      sum'=sum+len*2。

      y的最长链=x的最长链+len

3.如果x上没有y下面有

      sum'=sum-len*2。

      y的最长链不变。

最后的答案就是每个点的sum-max了。

第二种思路是对于sum一样处理。

而max则是i这个点到最远的点的距离。

那么就可以将所有点的deep值放进线段树中,当每转移到下一个点时,将下面子树内所有点的deep值减1,而其他的deep值加1,最后直接找deep最大值就可以了。

T3:

对于每一个牛棚是独立的。可以预处理出第i个牛棚用j次的代价,那么问题转化为将k次操作分给i个牛棚,每次操作对应着i的一个值,求最大代价。

那么直接dp,设f[i][j]表示前i个牛棚一共用了j次,则f[i][j]=min{ f [ i-1 ][ j-k ]+cost [ i-1 ][ k ]}

时间O(mk^2)。

实际上可以优化到k log m。

用堆维护所有牛棚中哪一个多用一次贡献最大(做差),一共取k次,即k log m。

检查要做好。

发布了199 篇原创文章 · 获赞 201 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/zsjzliziyang/article/details/103466165