CDQ分治学习

通过这个题SPOJ LIS2学习了下CDQ分治,巧妙之处在于区间拆半,用左区间来更新右区间。
题目就是求最长的二维LIS,也就是三维偏序。

把每对值 (x,y) 的下标作为第一维, x 作为第二维,y 作为第三维,然后分区间地去处理。大致代码如下:

void CDQ(int L,int R)
{
    if(L == R) return;
    int m = (L+R) >> 1;
    CDQ(L,m);
    solve(L,R);
    CDQ(m + 1,R);
}

相当于一个二叉树上的中序处理,在solve(L,R)时,就是分为区间 [L,mid] , [mid+1,R] ,然后对两个区间都根据y作为关键字排序,这个时候每个区间内的第一维可能会被打乱,但是总体来说,右区间的x关键字还是大于左区间的,所以接下来就是利用区间 [L,mid] 去更新 [mid+1,R] ,部分代码如下:

    int j = L;
    //update[m+1,R] by [L,m] for x is sorted
    for(int i = m+1;i <= R;i ++){
        while(j<=m && a[j].y<a[i].y){
            update(a[j].z,dp[a[j].x]);
            j++;
        }
        int id = a[i].x;
        dp[id] = max(dp[id],read(a[i].z-1) + 1);
    }

解释下,update就是单点更新,每次更新完后,再去查询所有小于 a[i].z 的值里边最大的一个,去更新 dp[id]

如果你还有地方没看懂的话,点 CDQ分治

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值