CF1895G:Two Characters, Two Colors(一道基于序列二选一带有位置影响的网络流模型使用看起来简单写起来恶心的平衡树进行优化的好题)
G:
题意:给出01序列,给出 r 序列和 b 序列,每个位置选择 \(r_i\) 或 \(b_i\),保留01序列中选择 \(r_i\) 的位置,总贡献为选择的数字和减去保留后的01序列的逆序对个数,请你最大化总贡献。nlogn
第一眼是dp,看到数据范围放弃了,第二眼是网络流,看到数据范围放弃了。但是,这不失为一个学习网络流模型的好情景。
Solution:
基于序列二选一的网络流,每个位置分别向源汇点连边,一条边权为 \(r_i\),一条边权为 \(b_i\),为了让后面逆序对的连边流量是负数(以及和其他题解保持一致。。),我们设割掉的边表示减去的贡献,并假设一开始贡献是两个数列所有数之和。
如果没有逆序对,每个位置会割掉 \(r_i\) 和 \(b_i\) 中较小的那条边,表示总贡献减去这条边(这条边我们不选),相当于二选一每次都选较大值。
考虑逆序对对答案的影响,将较小边的流量割去后,会保留一些边,意味着我们要选这些权值。根据题意,如果我们选一前一后两个 \(r_i\),可能会导致逆序对产生,此时贡献减一。也就是我们的网络流图中,如果 \(i\) 保留 \(r_i\) 边,\(j\) 保留 \(r_j\) 边,可以再产生1的流量。
不难想出最终的建图:所有01序列中1位置的点连线它后面0位置的点;第 i 个位置如果为1,向源点流量为 \(r_i\),汇点流量为 \(b_i\);第 i 个位置如果为0,向源点流量为 \(b_i\),汇点流量为 \(r_i\);
这样保留下来的边会不断地流逆序对造成的影响,直到逆序对的贡献全部减去,或者将源汇点的 \(r_i\) 连线流完表示二选一的反悔。
基于二选一带有位置影响的网络流模型大致是这样。
然后发现网络流太慢哩。而且这张图的构造又十分简单,我们可以模拟网络流的过程,这个动手画一下就能发现。
01序列中1的位置,就是向中间添加 \(r_i-b_i\) 的流量(前提是流量大于0),而0的位置,就是减去前面 \(r_i-b_i\) 条边,因为前面的流量与位置无关,每次贪心选最大的 \(r_i-b_i\) 条边减一。发现题意转化为:
1:加入一个权值。
2:前k大的数减一(变成0就消去)。
这题不失为一道平衡树小练习。因为我们平衡树的中序是按大小排序的,区间减一可能会导致大小变化,仔细思考会发现只有最小的那个数才会发生变化(其实是写到一半的时候才发现的呵呵),我的处理方式是每次将最小的数拿出来重新插入平衡树。
因为不会FHQ,我用的是Splay:
如图,黄色部分为前k大的数,将它们splay到一棵子树内打标记(黄色被劈成一半是因为第k大的数可能有好多个),就将这个被劈开的数拿掉重新插入就好(我是将它splay到inf底下然后把它右儿子连给inf,总之具体怎么搞自己动手一下就会了)。