• 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;
        }
    }
    //这段代码其中有许多可以优化的地方,但是不要在意细节,主要是为了更加方便地理解算法
    

  • 相关阅读:
    【翻译自mos文章】rman 标准版和企业版的兼容性
    HDU 1010 Tempter of the Bone
    uva 10716 Evil Straw Warts Live(贪心回文串)
    适配器及适配器模式
    Android推送技术研究
    【hadoop2.6.0】倒排索引遇到问题了
    【hadoop2.6.0】MapReduce原理
    【hadoop2.6.0】一句话形容mapreduce
    【leetcode】Median of Two Sorted Arrays(hard)★!!
    【leetcode】Merge k Sorted Lists
  • 原文地址:https://www.cnblogs.com/1436177712qqcom/p/9270255.html
Copyright © 2020-2023  润新知