先锐评一下幽默题解区,一篇自称单根号的题解是假的,另一篇自称单根号的题解没给代码,姑且认为她是变化莫测的。剩下的做法全部带
log。所以来一篇正常题解。
先考虑每辆车到哪个加油站。显然是让第
i 左的车去第
i 左的加油站。下面给出证明:
假设第
i 左的车位置为
x,去的加油站位置为
X。第
i+1 左的车位置为
y,去的加油站位置为
Y。如果
X≥Y,则交换两车的目的地后:
- x≤y≤Y≤X:交换前总路程为 X−x+Y−y,交换后总路程为 Y−x+X−y,不劣。
- x≤Y≤y≤X:交换前总路程为 X−x+Y−y≥X−x,交换后的总路程为 Y−x+X−y≤X−x,不劣。
- x≤Y≤X≤y:交换前总路程为 X−x+Y−y≥y−x,交换后总路程为 Y−x+y−X≤y−x,不劣。
- Y≤x≤y≤X:交换前总路程为 X−x+y−Y≥X−Y,交换后总路程为 x−Y+X−y≤X−Y,不劣。
- Y≤x≤X≤y:交换前总路程为 X−x+Y−y≥y−Y,交换后总路程为 x−Y+y−X≤y−Y,不劣。
- Y≤X≤x≤y:交换前总路程为 x−X+y−Y,交换后总路程为 x−Y+y−X,不劣。
因此记第
i 左的车去的加油站为
pi,则
pi 单调不降。故第
i 左的车去的加油站为第
i 左的。
Q.E.D.
那么我们记
ai,bi 均为排过序的数组,则要求单点修改
ai,然后对新数组重新排序,求
i=1∑n∣ai−bi∣。
这个比较困难,考虑把每一时刻车所在位置和加油站所在位置上的点
P 在数轴上表示出来离散化一下,则一共有
O(n+q) 个点,且每一段路程一定由若干个相邻点构成的线段组成。所以考虑每一条线段的贡献。
记从左至右第
i 条线段长度为
wi,起点为
Pi,终点为
Pi+1。记
sai 表示当前
Pi 之前车的数量,
sbi 表示
Pi 之前加油站的数量。则第
i 条线段会被经过
∣sai−sbi∣ 次。
因为考虑什么情况下会经过这条线段,显然要求车和加油站分布在她的两侧。不妨令
sai≥sbi,则对于
j∈[1,sbi] 有
aj,bj≤Pi,对于
j∈(sbi,sai] 有
aj≤Pi<bj,对于
j∈(sbi,n] 有
aj,bj>Pi。因此在两侧的就是
(sbi,sai] 内的这些车和加油站,故被经过
∣sai−sbi∣ 次。对于
sai<sbi 的情况是同理的。
记
si=sai−sbi,则对于一次挪车的操作,设其从
Px 挪至
Py,不考虑
x=y。若
Px<Py,相当于区间
[x,y) 内
sai 减
1 即
si 减
1。否则相当于区间
[x,y) 内
sai 加
1 即
si 加
1。
现在问题变成
si 区间加减
1,求全局
i=1∑m∣si∣wi,其中
m 是线段的数量。
考虑以
O(n+q) 为块长分块,离线逐块处理。记当前块为
[L,R]。对于查询把绝对值拆开,对于
si≥0 的部分贡献为
si≥0∑siwi,对于
si<0 的部分贡献为
−si<0∑siwi。
考虑整块修改。维护辅助数组
si′ 和全局加标记
T 使得任意时刻
si′+T=si。
当全局
si 加
1 时,
T 加
1,对于原来
si≥0 的部分,
∣si∣ 加
1,贡献增加
si≥0∑wi。对于原来
si<0 的部分,
∣si∣ 减
1,贡献减少
si<0∑wi。
当全局
si 减
1 时,
T 减
1,对于原来
si≥1 的部分,
∣si∣ 减
1,贡献减少
si≥1∑wi。对于原来
si≤0 的部分,
∣si∣ 加
1,贡献增加
si≤0∑wi。
维护
po=si≥0∑wi,ne=si<0∑wi,cnj=si′=j∑wi。则当前块对修改后答案相较于修改前增加、减少的贡献可以通过
po,ne,cn−T 表示出来。同时
po,ne 的变化量也可以被
cn−T,cn−T−1 表示出来。注意这里给下标加一个偏移量。注意到
∣si∣≤n,偏移量设为
n 即可,且
cn 占用的空间为
O(n)。
每次整块修改都是
O(1) 的,一共进行
O(qn+q) 次,故总时间复杂度为
O(qn+q)。
对于散块修改,下放标记然后重构即可。但是重构
cn 的时候不能暴力遍历值域。注意到整块修改不会修改
si′,因此
cn 中不为
0 的下标只有
sL′,…,sR′ 这些,存储每次的
si′ 并在重构时清空这些位置即可。单次时间复杂度为
O(n+q),一共
O(q) 次,故总时间复杂度
O(qn+q)。
综上,该做法时间复杂度为
O(qn+q),空间复杂度为
O(n+q)。