• CDQ分治详解


    解决问题:

    这类问题一般是给你一个长度为 n 的序列,然后让你统计有一些特性的点对(i,j)有多少个,又或者说是找到一对点(i,j)使得一些函数的值最大之类的问题

    算法流程:

    1. 找到当前序列中点mid

    2. 将所有的点分为三类

    第一种是(1leq ileq mid 1leq jleq mid)

    第二种是(1leq mid+1 mid+1leq jleq n)

    第三种是(mid+1leq ileq n mid+1leq jleq n)

    1. 将(1,n)序列分为两部分(1,mid)和(mid+1,n)

    会发现第一类点和第三类点分别被完全包含在两个序列

    考虑如何求解第二类点,结合一下题来说明一下吧

    经典问题

    三维偏序:给定一个序列,每个点有两个性质((a_i,b_i)),求这个序列中有多少个点对满足(i < j,a_i < a_j,b_i < b_j)

    假设我们现在在solve(l,r),而且现在我们已经求出了solve(l,mid)和solve(mid+1,r)

    那么我们现在就是统计(lleq ileq mid,mid+1leq jleq r)的点对(i,j)满足(i < j,a_i < a_j,b_i < b_j)

    然后我们发现(i < j)这个条件没有用了,因为一定满足

    剩下两个条件我们可以吧(l,mid)和(mid+1,r)的点分别按照a排序,然后在(mid+1,r)中枚举j,把所有的(a_i < a_j)全部插入到数据结构中

    因为a已经排好序了,所以对于后一个的j,满足前一个j的(a_i)一定满足后一个j

    核心代码:

    void cdq(int l,int r){
    	if (l == r) return;
    	int mid = (l+r >> 1);
    	cdq(l,mid),cdq(mid+1,r);
    	sort(a+l,a+mi+1,cmpy),sort(a+mid+1,a+r+1,cmpy);
    	int j = l;
    	for (int i = mid+1;i <= r;i++){
    		while (a[j].y <= a[i].y&&j <= mid) add(a[j].z,a[j].w),j++;
    		a[i].ans += query(a[i].z;)
    	}
    	for (int i = l;i < j;i++) add(a[i].z,-a[i].w);
    }
    
  • 相关阅读:
    Python-list
    C3P0数据库连接池使用中的问题
    不变类和可变类
    apollo配置中心部署文档
    Apollo使用文档(Java)
    Redis偶发连接失败案例分析
    创建Kibana耗时报表
    Session服务器配置,如何保存在专门的StateServer服务器中
    Linux命令对应的英文全称
    IIS记录真实来源IP,Advanced Logging(高级日志)的安装以及X-Forwarded-For的配置
  • 原文地址:https://www.cnblogs.com/little-uu/p/14743979.html
Copyright © 2020-2023  润新知