CDQ分治
通过分治来用一个子问题来计算对另一个子问题的贡献,先考虑前半部分,再考虑后半部分,再考虑前半部分对后半部分的影响
处理修改独立,询问可离线的一类问题,对时间分治,用左边的修改处理右边的询问
可以用来解决三维偏序问题
\(code :\)
void cdq(int l,int r)
{
if(l==r) return;
int mid=(l+r)>>1;
cdq(l,mid),cdq(mid+1,r);
sort(q+l,q+mid+1,cmp2);
sort(q+mid+1,q+r+1,cmp2);
int j=l;
for(int i=mid+1;i<=r;++i)
{
while(q[j].b<=q[i].b&&j<=mid)
{
update(q[j].c,q[j].val);
j++;
}
q[i].ans+=query(q[i].c);
}
for(int i=l;i<j;++i) update(q[i].c,-q[i].val);
}
动态逆序对:转删除为插入,转化为三维偏序问题,\(Time_i<Time_j,Val_i>Val_j,Pos_i<Pos_j\)或\(Time_i<Time_j,Val_i<Val_j,Pos_i>Pos_j\)
\(code :\)
void cdq(int l,int r)
{
if(l==r) return;
int mid=(l+r)>>1,j;
cdq(l,mid),cdq(mid+1,r);
sort(p+l,p+mid+1,cmp),sort(p+mid+1,p+r+1,cmp);
j=mid+1;
for(int i=l;i<=mid;++i)
{
while(p[i].val>p[j].val&&j<=r) update(p[j++].time,1);
ans[p[i].time]+=query(p[i].time);
}
for(int i=mid+1;i<j;++i) update(p[i].time,-1);
j=mid;
for(int i=r;i>mid;--i)
{
while(p[i].val<p[j].val&&j>=l) update(p[j--].time,1);
ans[p[i].time]+=query(p[i].time);
}
for(int i=mid;i>j;--i) update(p[i].time,-1);
}