可撤销贪心

例题见JZOJ4726。

以这一道题为例,我们可以贪心,每一次从剩下可选的数中选出一个最大的,但这样显然是错的。那么怎么办呢?我们可以考虑让贪心变得可撤销。

假设当前我们选了第i个数,那么它的贡献就是a[i]。但是最优解有可能不选它,如果不选它的话,那么就会选它的两侧相邻的点,如果这样选的话贡献就是a[i-1]+a[i+1]。所以要把之前的贪心撤消了,就相当于把ans加上a[i-1]+a[i+1]-a[i]。

具体做法如下:首先把所有a[i]加入一个大根堆里。再记录一下每一个数的前驱和后继,即l[i]=i-1,r[i]=i+1(当然,l[1]=n,r[n]=1)。然后取m次。每一次取堆顶。假设当前取出的是a[i],那么我们把a[l[i]]+a[r[i]]-a[i]加入大根堆,再把l[i]和r[i]删掉(也就是更新前驱和后继)。这样做就可以了。

为什么要记录前驱和后继呢?因为如果我们要撤销对a[i]的贪心,那么就要对a[i]的前驱的后继做操作,也就相当于把这三个点缩成一个点,所以要记录前驱和后继。

总结:

可撤销贪心就是把不选这一个点的贡献减去选这一个点的贡献的值加入所有选择方案里,但是要注意有关的点要缩成一个点。

你可能感兴趣的:(【初中部,NOIP提高组,】模拟赛B)