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);
}
原文地址:https://www.cnblogs.com/lhm-/p/12229595.html