CDQ跑的比分治快得多
首先 我们可以把每一个点看成一个三元组(x, y, z) x 表示它当前的值 y 表示的在序列中的编号 z 表示它的时间 即第z次操作后的这个点
所以 如果某个点P在平面上的左上方有点(值小于P并且位置在P之后) 后者右下方(恰好相反)的地方有点 就会形成一个逆序对
在一开始我们很容易求出每一个点形成的逆序对总数 每次删除的时候从ans中减去
然而 在CDQ分治的过程中 树状数组需要多次使用 每次清空需要耗费大量时间 这个时候我们加入一个时间轴 只有在当前时间的点才进行统计 这样就避免了清空的操作 节省了时间
还有一个问题 每次一个点x删除时 会减去他的逆序对(x, y) y删除的时候也同样会减去 这样就重复了 要怎样处理这样的问题呢?
我们将已经删除的元素看作一个删除序列 定义d[i]为删除该元素后删除序列中新增的逆序对的个数 这就是减重复了的个数 每次删除一个数过后ans要加上d[i];
这样 每一个删除操作都成为了一个三元组(x, y, id) 我们可以用CDQ根据id排序 但是还剩下两位 处理的时候会有困难 所以我们把整个序列按y排序 这样就可以了
#include
#include
#include
#include
#include
#include