CDQ分治学习
2015-11-27 13:04
295 查看
通过这个题SPOJ LIS2学习了下CDQ分治,巧妙之处在于区间拆半,用左区间来更新右区间。
题目就是求最长的二维LIS,也就是三维偏序。
把每对值(x,y) 的下标作为第一维,x 作为第二维,y 作为第三维,然后分区间地去处理。大致代码如下:
相当于一个二叉树上的中序处理,在solve(L,R)时,就是分为区间[L,mid], [mid+1,R],然后对两个区间都根据y作为关键字排序,这个时候每个区间内的第一维可能会被打乱,但是总体来说,右区间的x关键字还是大于左区间的,所以接下来就是利用区间[L,mid] 去更新[mid+1,R],部分代码如下:
解释下,update就是单点更新,每次更新完后,再去查询所有小于a[i].z 的值里边最大的一个,去更新dp[id]。
如果你还有地方没看懂的话,点 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分治
相关文章推荐
- hdu 5324 树套树、cdq分治
- 【Violet3】【BZOJ2716】天使玩偶
- 【BZOJ4311】向量
- 【BeiJing2011】【BZOJ2458】最小三角形
- HDU 5412 CRB and Queries 求区间第k小 CDQ分治+整体二分
- HDU 5324 Boring Class(分治+树状数组)
- 1752. [BOI2007]摩基亚Mokia (cdq分治模板题)
- hdu 5126 stars(三维空间cdq分治)
- cdq分治模板
- 【分治】 BZOJ 1176 [Balkan2007]Mokia
- [BZOJ2244][SDOI2011]拦截导弹(DP+CDQ分治)
- HDU - 5730 CDQ分治 + FFT
- HDU - 1166 CDQ分治
- cogs 1752. [BOI2007]摩基亚Mokia
- hdu 1166 敌兵布阵(cdq分治)
- 对CDQ分治的一些见解
- [BZOJ1176][[Balkan2007]Mokia][CDQ分治]
- hdu5618Jam's problem again (CDQ分治)
- HDU1166 敌兵布阵 线段树||树状数组||CDQ分治 入门题复习
- bzoj 2726: [SDOI2012]任务安排