做了半个下午,写了大半个晚上,真的是 dirty work。
首先一个点只会和父亲交换一次,并且交换了两边就相对独立了。因此我们考虑从这个方面入手 dp。
设 \(f_{i,x,y}\) 表示 \(i\) 和父亲交换的时候,换出去 \(d_x\) ,换进来 \(d_y\) ,最少的子树内交换次数。容易做到 \(O(n^3)\)。
但是你发现这个东西非常不好,因为状态数就是 \(O(n^3)\) 的。如果 \(y\) 也在 \(i\) 的子树内且和 \(x\) 不同子树那么就是 \(O(n^2)\) 了。
能不能实现呢?试试看修改 dp 状态,我们现在不要知道换进来几个,而是把换进来的数换了几次记到状态里面去。设 \(f_{i,x,y}\) 表示 \(i\) 换出去的是 \(d_x\),换进来的走了 \(y\) 步,这样状态数降到了 \(O(n^2)\) ,并且看上去有优化的余地。我们来尝逝讨论一下。
-
\(i\) 没有儿子,那么只有 \(dp_{i,i,0}=0\)。
-
\(i\) 只有一个儿子,记作 \(v\),那么有两种情况:
- 先和子树交换,再和父亲交换:\(dp_{v,j,dep}+d_i\times (dep+1)+d_j\to dp_{i,j,0}\)。
- 先和父亲交换,再和子树交换:\(dp_{v,j,dep}+d_j\to dp_{i,i,dep+1}\)。
-
\(i\) 有两个儿子,记作 \(L\) 和 \(R\),因为哪个先走是对称的,所以假设 \(L\) 先走。
- 先和父亲交换:\(dp_{L,j_1,d_1}+dp_{R,j_2,d_2}+d_{j_1}(d_2+2)+d_{j_2}\to dp_{i,i,d_1}\)
- 先和 \(L\) 交换,再和父亲交换:\(dp_{L,j_1,d_1}+d_i\times d_1+dp_{R,j_2,d_2}+d_{j_2}\to dp_{i,j_1,d_2}\)。
- 先和 \(L,R\) 交换,再和父亲交换:\(dp_{L,j_1,d_1}+d_i(d_1+1)+d_{j_1}(d_2+2)+dp_{R,j_2,d_2}+d_{j_2}\to dp_{i,j_2,0}\)。
直接转移大概是 \(O(n^3)\) 的,如果你用指针分配空间大概能过 \(64\)。
优化的话发现三方部分主要在两个儿子的部分,而这些都可以斜率优化,于是就做到了 \(O(n^2)\)。细节巨大多,还只有这么小的样例。
标签:P8294,省选,交换,dep,父亲,联考,dp From: https://www.cnblogs.com/275307894a/p/17176892.html