CDQ分治与整体二分小结
2017-08-26 22:38
281 查看
前言
这是一波强行总结。下面是一波瞎比比。
这几天做了几道CDQ/整体二分,感觉自己做题速度好慢啊。
很多很显然的东西都看不出来 分治分不出来 打不出来 调不对
上午下午晚上的效率完全不一样啊。
完蛋.jpg 绝望.jpg。
关于CDQ分治
CDQ分治,求的是三维偏序问题都知道的。求法呢,就是在分治外面先把一维变成有序
然后分治下去,左边(l,mid)关于右边(mid+1,r)就不存在某一维的逆序了,所以只有两维偏序了。
这个时候来一波"树状数组求逆序对"的操作搞一下二维偏序
就可以把跨过中线的,左边更新右边的情况计算出来。
[b]注意:只计算左边的操作对右边的询问的贡献![/b]
然后左右两边递归处理就好了。
正确性:按照线段树的形态递归的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,加个单调栈。
还有一个就是高维偏序问题。
cogs上的2479 HZOI2016 偏序 就是四维偏序板子。
后面还有两个加强版,到了七维,不是CDQ干的事情,详情请见这个PPT。
校内交流所以做的不是很严谨(吐舌)
这里只谈论四维偏序,即a<a' b<b' c<c' d<d'。
做法是喜闻乐见的CDQ套CDQ套树状数组。
有个很妙的博客:Candy?
首先在外面按照a排好序。
进第一层CDQ。先递归处理,然后标记本来是在mid左边还是右边的,左1右0,然后按b排序。
[b]还是只统计左边部分跨过中线对右边部分的贡献。[/b]
按照b排好序后,就变成了统计标记为0的点的"在它左边的、标记为1的、(c,d)都小于它的点的个数"。
"在它左边+(c,d)都小于它" = 三维偏序。
复制到另一个数组里再做一次cdq就可以了。
复杂度O(nlog^3n)。
inline bool check(int mid){ int t1=0,t2=0; for(int i=1;i<=m;++i){ if(calc(i,mid))que[1][++t1]=i; else que[2][++t2]=i; } if(t1>=k){ m=t1; for(int i=1;i<=m;++i)opt[i]=que[1][i]; return 1; } else{ m=t2; for(int i=1;i<=m;++i)opt[i]=que[2][i]; k-=t1;return 0; } } ... int l=...,r=...,ans=-1; while(l<=r){ int mid=(l+r)>>1; if(check(mid))r=mid-1,ans=mid; else l=mid+1; }
2.0
(如上面代码有错误请指出)
分析起来复杂度并没有什么改变......
但是如果把二分答案看成一棵二叉树,每个点(区间[l,r])的权值为check的操作数。
把当前是第几次二分看成这个区间的深度(层)。
每一层的区间相互没有交。
那么有一个优秀的性质:只有log层,每一层的点权和为O(m)。
所以这个时候对于多组询问一起处理,复杂度为O((m+q)logn)。
二分答案,然后把没有用的操作扫进右边,和答案在[mid+1,r]的询问一起递归处理。
把有用的操作放进左边,减去不变的贡献,和答案在[l,mid]的一起递归处理。
[b]注意答案在[mid+1,r]的询问要算上放进了左边的操作的贡献,开个变量记下来/直接减掉都可以。[/b]
[b]注意整体二分在solve内的复杂度一定只能与区间长度线性相关,不能每次都有别的复杂度![/b]
比如一次solve的复杂度是O(lenlogn)就可以,O(len+sqrt(n))就不行。
大概就是这么一个东西。
复杂度?和CDQ是一样的,都是O(f(len)logn)。
例题?BZOJ3110 K大数查询 Codevs Meteors。
一样的套路了。
关于一些要注意的地方
归并一定要把剩下的搞完!每次我都忘记这码子事!树状数组不能暴力清零!记个time或者依葫芦画瓢减回去都可以,一定不能清零!
不要在CDQ里面套sort,太慢辣!(一定进不了第一版的!)
相关文章推荐
- CDQ分治与整体二分小结
- [CDQ分治与整体二分]个人对CDQ分治与整体二分的理解
- [CDQ分治与整体二分]个人对CDQ分治与整体二分的理解
- HDU 5412 CRB and Queries 求区间第k小 CDQ分治+整体二分
- 整体二分 && CDQ分治
- 2017 暑假艾教集训 day9(整体二分 + cdq分治 cdq真是我女神!!!)
- 整体二分&cdq分治 ZOJ 2112 Dynamic Rankings
- 分治挑战数据结构——小记整体二分和CDQ分治
- 整体二分&CDQ分治:[BZOJ2527][POI2011] meteors [BZOJ3295][CQOI2011] 动态逆序对
- Uva7716 The Cure(CDQ分治 + 整体二分)
- HDU - 5618 Jam's problem again(cdq分治和整体二分)
- 主席树+CDQ分治+整体二分
- [BZOJ3110][ZJOI2013]K大数查询-CDQ分治-整体二分
- HDU 5412 CRB and Queries(整体二分 | CDQ分治)
- CQD(陈丹琦)分治 & 整体二分——专题小结
- cdq分治和整体二分
- 【cdq分治】cdq分治与整体二分学习笔记Part1.整体二分
- POI2011 Meteors(CDQ分治 + 整体二分)
- 整体二分\cdq分治——洛谷P3332 [ZJOI2013]K大数查询
- 【cdq分治】cdq分治与整体二分学习笔记Part2.cdq分治