loj 3039
NKOJ

Description

\(n\)个蛋糕,每个蛋糕有\(w_i,h_i\)。选\(m\)个蛋糕满足\(\sum\limits_{j=1}^mw_{k_j}-\sum\limits_{j=1}^m|h_{k_j}-h_{k_{j+1}}\ |\)
因为蛋糕摆成一个环所以\(k_1=k_{m+1}\)

Solution

我因为最近天天做dp,直接就往dp上想的,其实是思维僵化。
然后本来可以骗46分的,因为没有考虑到答案可能是负数+数据点捆绑直接宝菱。
dp就前缀和优化dp就可以做了,很好写。
当然前面肯定要想到\(\sum\limits_{j=1}^m|h_{k_j}-h_{k_{j+1}}\ |\)这个的最小值,显然是按\(h\)从小到大排后得到的,因此其实是\(2*(maxh-minh)\)
这样按\(h\)排序,消除影响。
枚举最后一个选的点\(i\),发现第一个选的点\(j\)是具有决策单调性的(只会打表)
整体二分+可删对顶堆

这东西挺恶心的,总之我调了好久,经常推翻重来

总结一下:

整体二分:维护两个指针\(tl\),\(tr\),复杂度是\(nlog_2^2n\)的因为\(log_2n\)层,每次\([L,R]\)结束时,\(tl=L,tr=R\)。左递归开始时肯定是取\([L,R]\)中一个点\(pos\),\(tl=pos,tr=pos\),左边递归结束时一定是也\(tl=pos,tr=pos\)(左dfs树最靠右的叶子),此时再右递归转移到 \(tl=R,tr=R\)。考虑这一层的转移,显然是\(R-L+1\)次,每次\(O(log_2n)\),而又有有\(log_2n\)层。
当然上面的复杂度证明中,不一定是确切的等于(如 \(tl\) 会有和 \(mid-m+1\)\(min\),每层跟\(mid\)有关总体也是\(nlog_2n\)级别的),易证影响不大/kk。

对顶堆:因为你需要维护前\(m\)大的和(\(sumw\)),如果你只存一个大根堆,删除或者加入是维护不了的。
因此前\(m\)大的数存入小根堆\(Q1\)里,其它小的数存入大根堆\(Q2\),每次加入一个数判断如果大于\(Q1\),\(Q2\)分界,把\(Q1.top()\)加入\(Q2\),把该数加入\(Q1\)。否则直接加入\(Q2\)
然后删除也维护两个可删堆\(D1,D2\)。每次删除的时候判断删的数是在\(Q1\)中则加入\(Q2\),反之……
每次取出堆顶前判断是如果已经在可删堆内,直接删了(这是可删堆的常规操作……)

!!! 这里我犯过一个错误

你维护的\(sumw\)不是你\(Q1\)里面实际所有值的和。而是里面没有在\(D1\)中(没被删)的和。
\(Q1-D1\)才是真正的前\(m\)大。\(Q1\)里面还存在着一些已经死去的傀儡……
所以实际上\(Q1.size()\)不一定等于\(m\),我们需要单独维护一个\(sz1\)(这个很简单)

实现细节:不知道我的实现方式会不会比别人复杂

强制\(Q1\),\(Q2\)的堆顶是存在的(没被删),需要每次\(pop()\)后,删点即可。
Add的就是上面对顶堆说的那堆。
Del比较复杂,如果删除的是在\(Q1\)中的,用\(Q2.top()\)替代删除的那个,即把\(Q2.top()\)加入\(Q1\),删除的值加入\(D1\)。这样也保证了\(sz1\)守恒。

以后写博客尽量宏观一点,不要太啰嗦,不过我感觉题目都好细节呀。