您的位置:首页 > 其它

CDQ分治学习

2015-11-27 13:04 295 查看
通过这个题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分治
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  CDQ分治