多方查找找到了2008年陈丹琪引入CDQ分治的 从《Cash》谈一类分治算法的应用.doc ,CDQ分治的名字由来也是她.

  什么叫CDQ分治呢?来看一道二维数点题p1357.

  CDQ分治,二维数点与三维数点,p1357与p2026与p2027与p2028与p2029

  看了一眼题,我会树状数组!

  现在拿它来引入CDQ分治.先全部按照x排序,由于区间[mid+1,r]不会再对区间[l,mid]有贡献,对于区间[l,r]内的贡献都可以分三步进行.

  1.算区间[l,mid]内部相互的贡献

  2.算区间[mid+1,r]内部相互的贡献

  3.算[l,mid]对于[mid+1,r]的贡献

  现在考虑如何更快的计算第3步?假设1,2步后,两个小区间内部变成了按y排序的,我们像归并一样的把两个小区间按y合并成一个大区间并得到[l,mid]对于[mid+1,r]的贡献.

  先放一个nlog^2n的算法

bool Orz(node a,node b)
{
    return a.x<b.x;
}
void CDQ(int l,int r)
{
    if(l==r)
        return ;//自己对自己当然没贡献了
    int mid=(l+r)/2;
    CDQ(l,mid);
    CDQ(mid+1,r);
    //简陋的树状数组实现贡献统计
    for(int i=l;i<=mid;i++)//怎么还用树状数组啊?
        add(o[i].y,1);
    for(int i=mid+1;i<=r;i++)
        ans[o[i].i]+=ask(o[i].y);//算贡献
    for(int i=l;i<=mid;i++)//怎么又减回去了啊?
        add(o[i].y,-1);
    sort(o+l,o+r+1);//简陋的sort排序
}
int main()
{
    freopen("123.in","r",stdin);
    n=read();
    for(i=1;i<=n;i++)
    {
        o[i].x=read();
        o[i].y=read();
        o[i].i=i;//记录原始位置
    }
    sort(o+1,o+1+n,Orz);
    CDQ(1,n);//调用分治
    for(i=1;i<=n;i++)
        cout<<ans[i]<<endl;
}
简陋的CDQ分治

相关文章:

  • 2022-01-14
  • 2021-11-11
  • 2021-09-09
  • 2022-12-23
  • 2022-12-23
  • 2022-02-15
  • 2022-12-23
  • 2021-08-15
猜你喜欢
  • 2021-08-08
  • 2021-10-31
  • 2021-12-06
  • 2021-09-15
  • 2021-04-18
相关资源
相似解决方案