跳到主要内容

CDQ 分治

参考资料

简介

CDQ 分治 用分治处理带「时间维」的偏序与数点问题。按第一维分治,递归处理左右两半后,专门统计 左半对右半 的跨区间贡献:此时左右各自已按第二维有序,归并的同时用树状数组维护第三维即可。常用于三维偏序、动态逆序对等,时间复杂度通常为 O(nlog2n)O(n\log^2 n)

实现

349 Bcpp
void cdq(int l,int r)
{
if(l==r)return;
cdq(l,mid);
cdq(mid+1,r);
int p1=l,p2=mid+1;
for(int i=l;i<=r;i++)
{
if(p1<=mid&&(p2>r||a[p1].y<=a[p2].y))
{
b[i]=a[p1++];
bit.add(b[i].z,1);
}
else
{
b[i]=a[p2++];
ans[b[i].id]+=bit.sum(b[i].z);
}
}
for(int i=l;i<=mid;i++)bit.add(a[i].z,-1);
for(int i=l;i<=r;i++)a[i]=b[i];
}

例题

nn 个元素,第 ii 个元素有 ai,bi,cia_i,b_i,c_i 三个属性,设 f(i)f(i) 表示满足 ajaia_j\leq a_ibjbib_j\leq b_icjcic_j\leq c_ijij\ne ijj 的数量。

对于 d[0,n)d\in[0,n),求 f(i)=df(i)=d 的数量。