CDQ分治

CDQ分治与一般的分治的差别是

CDQ分治是前半部分的来处理后半部分的问题

因为先按第一关键字如果从小到大来排

前半部分的的所有的按第一关键字一定是小于后半部分的任意一个的

所以此时前半部分可以按第二关键字来排

第一关键字就没有影响了

就可处理第二关键字对第后半部分的影响

依次类推就可处理问题


下面例子是从一个大佬那转的大佬的博客(点击打开链接)

举个例子:在二维坐标系中,有n个点,m个询问。对于每个询问(x, y),求点(x1, x2) ,x1<= x && y1 <= y 有多少个。

当然,这题用树状数组就直接能写了。但是我们在这里用CDQ分治来解决一下这个问题。

我们将n个点看做是n个更新,并和m个询问放在一起。定义一个结构体用vector存起来。

void sovle1(int l, int r, vector<Struct>vec1) {//分解
    //在这里将vec1[l, r]按x从小到大排序
    int mid = (l + r) / 2;
    solve1(l, mid);
    solve1(mid + 1, r);//划分成相互独立的子问题
    //将vec1[l, mid]中的更新操作 和 vec1[mid + 1, r]中的询问操作,存到一个vec2中 
    solve2(l, r, vec2);//左半边的更新操作和右半边的询问操作之间有联系
}
void solve2(int l, int r, vector<Struct>vec2) {//建立问题
//此时在solve2中已经不需要管x了。在vec2中所有的更新操作的x必然小于等于询问操作的x。**证是这句话启发我
    
    //在这里将vec2[l, r]按y从小到大排序
    int mid = (l + r) / 2;
    sovle2(l, mid);
    solve2(mid + 1, r);//独立子问题
    //将vec2[l, mid]中的更新操作和vec2[mid + 1, r]中得询问操作存到一个vec3中
    solve3(l, r, vec3);//
}
void solve3(int l, int r, vector<Struct>vec3) {//处理
//此时在solve3中,x和y都是已经排好序的。从前到后遍历该更新更新该询问询问就好。
    int cal = 0;
    for(Struct tmp: vec3) {
        if(tmp.type == Update)  ++cal;
        else tmp.query_anser += cal;
    }
}
//这段代码其中有许多可以优化的地方,但是不要在意细节,主要是为了更加方便地理解算法

转载于:https://www.cnblogs.com/1436177712qqcom/p/9270255.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值