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

  • 相关阅读:
    JavaWeb--HttpSession案例
    codeforces B. Balls Game 解题报告
    hdu 1711 Number Sequence 解题报告
    codeforces B. Online Meeting 解题报告
    ZOJ 3706 Break Standard Weight 解题报告
    codeforces C. Magic Formulas 解题报告
    codeforces B. Sereja and Mirroring 解题报告
    zoj 1109 Language of FatMouse 解题报告
    hdu 1361.Parencodings 解题报告
    hdu 1004 Let the Balloon Rise 解题报告
  • 原文地址:https://www.cnblogs.com/1436177712qqcom/p/9270255.html
Copyright © 2011-2022 走看看