您的位置:首页 > 其它

CDQ分治与整体二分小结

2017-08-28 14:49 204 查看

前言

  这是一波强行总结。

  下面是一波瞎比比。

  这几天做了几道CDQ/整体二分,感觉自己做题速度好慢啊。

  很多很显然的东西都看不出来 分治分不出来 打不出来 调不对

  上午下午晚上的效率完全不一样啊。

  完蛋.jpg 绝望.jpg。

 

关于CDQ分治

  CDQ分治,求的是三维偏序问题都知道的。

  求法呢,就是在分治外面先把一维变成有序

  然后分治下去,左边(l,mid)关于右边(mid+1,r)就不存在某一维的逆序了,所以只有两维偏序了。

  这个时候来一波"树状数组求逆序对"的操作搞一下二维偏序

  就可以把跨过中线的,左边更新右边的情况计算出来。

  注意:只计算左边的操作对右边的询问的贡献!

  然后左右两边递归处理就好了。

  正确性:按照线段树的形态递归的CDQ分治,保证每一对三元组在线段树上都有且仅有一个LCA(这不废话吗),而这一组答案就会且仅会在LCA处计算。如果在LCA下面,点对不在一个work内自然不会计算。如果在LCA上面了,点对就在同一侧,不会互相更新。

  复杂度:设一次work的复杂度是f(len),则复杂度是O(f(n)logn)。

  一般都在分治里用树状数组,一般的复杂度就是O(nlog2n)的。

  一般是这样的套路:假设三维偏序分别为a,b,c;

  在main函数里保证a递增。

  然后在CDQ里先分治左右,传下去的时候a仍然递增,不破坏性质。

  然后分治完左右两边后,需保证左右两边分别b都是递增的(a不重要)。

  然后就是类似归并排序的操作了。

  此时左边的a肯定都小于右边的a,那么如果对于一个右边的元素

  之前类似归并的操作就可以保证所有小于b的左边的元素都已经遍历过。

  那么找c也小于它的?值域线段树/树状数组等数据结构维护一下就好了。

  然后你这么归并了一波后,就发现统计完答案后b是有序递增的了(这个时候a已经不重要了)。

  对于上层操作,符合"左右两边分别b是递增的"了。

  BZOJ陌上花开竟然是权限题?这是在搞笑。

  好吧BZOJ动态逆序对,之前写过的,做两次CDQ就好了。

  BZOJ稻草人,也是CDQ。

  

关于整体二分

  整体二分主要是把所有询问放在一起二分答案,然后把操作也一起分治。

  讲起来有些玄学。

  想想:二分答案的时候,对于一个答案,是不是有些操作是没用的?

  比如二分一个时间,那么时间后面发生的操作就是没有用的。

  二分一个最大值,比mid大的都是没用的。

  整体二分就是利用了这么一个性质。

  二分答案,然后把没有用的操作扫进右边,和答案在[mid+1,r]的询问一起递归处理。

  把有用的操作放进左边,和答案在[l,mid]的一起递归处理。

  注意答案在[mid+1,r]的询问要算上放进了左边的操作的贡献,开个变量记下来/直接减掉都可以。

  注意整体二分在solve内的复杂度一定只能与区间长度线性相关,不能每次都有别的复杂度!

  比如一次solve的复杂度是O(lenlogn)就可以,O(len+m)就不行。

  大概就是这么一个东西。

  复杂度?和CDQ是一样的,都是O(f(len)logn)。

  例题?BZOJ3110 K大数查询 Codevs Meteors。

  一样的套路了。

 

关于一些要注意的地方

  归并一定要把剩下的搞完!每次我都忘记这码子事!

  树状数组不能暴力清零!记个time或者依葫芦画瓢减回去都可以,一定不能清零!

  不要在CDQ里面套sort,太慢辣!

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: