题解:P10068 [CCO2023] Line Town
另外那篇在写啥???
注:这篇题解主要负责补充实现以及详细讲解“贡献可以树状数组简单计算”,默认大家已经会了原题解中“启示我们按照绝对值大小填数”前面的部分。
下面称所有绝对值相同的数为一类,符号相同且绝对值相同的数为一组,朝左和朝右分别表示这个数要放到当前考虑区间的最左端和最右端。
对于同一类数,我们枚举要往左边放
这个时候注意我们需要满足从前面贪心选择
之后我们还要考虑贡献分为哪些。画出上下两个数轴,把每一个点的起点和终点在上面和下面画出来并连边,那么任意两个数会产生贡献当且仅当他们的线段相交。答案显然是两两贡献之和。
我们把相交情况分成以下三种:
- 其中一个属于当前考虑的类,另一个属于其它类。
- 两个都属于其它类,但是在不同组。
- 两个都属于同组。
第一个贡献是容易计算的:
考虑最开始把每个数都放入树状数组,每次把当前类的数全都从树状数组删除然后计算树状数组中剩余的数(这些数的绝对值会比当前考虑的更小)和这一类的所有数的贡献。
对于一个数
同类不同组的贡献可以在枚举左右放的数的个数的时候动态更新。最初所有数都是朝右,之后按顺序每次把一个数改成朝左。
用两个树状数组代表两个方向的数都有哪些。当一个数
最后我们需要计算同组内的贡献以及选择前 / 后
具体的写法可以自己感受。