当前位置: 首页 > news >正文

总结-CDQ 分治

关于 CDQ 分治

CDQ 分治是一种思想而不是具体的算法,并且必须离线处理,用于维护具有偏序限制的问题。

偏序可以理解为大小关系。

经典三维偏序

CDQ 分治的经典应用。

给定每个元素,每个元素都有三个属性 \((x,y,z)\),要求统计所有满足三个偏序条件时的价值。

标准方法:sort 排序维护第一维偏序,用归并维护第二维偏序,用数据结构(树状数组、线段树)维护第三维偏序。

原理是在处理第二维的时候,使每一个左半区间元素对于每一个右半区间元素一定满足第一维的偏序,同时维护并统计第三维。

给个标准的框架:

归并版本:

归并排序版本的优点是常数小,缺点是必须要后序遍历并且偏序条件所关联的维度相同,要求统计价值时没有严格的先后顺序

经典的有严格的先后顺序的题目如 CDQ 分治套 DP 等,由于转移时要求所有先导状态都已被处理,所以这种题不能用归并版本来写,而需要用中序遍历的 sort 排序版本。

例题:[CQOI2011] 动态逆序对 - 洛谷

#define lowbit(x) ( x&(-x) )
int T[N];inline void update(int x)
{ for(;x<=n;x+=lowbit(x)) /*维护价值*/; }inline void Clear(int x)
{ for(;x<=n;x+=lowbit(x)) T[x]=0; }inline int query(int x)
{int sum=0;for(;x>0;x-=lowbit(x))/*统计价值*/return sum;
}struct ask
{ int x,y,z; }Q[N],tmp[N];
int ans[N];bool rule_y(ask u,ask v)
{ return u.y<v.y; }bool rule_x(ask u,ask v)
{ return u.x<v.x; }void cdq(int l,int r)
{if(l==r) return ;int mid=l+r>>1;cdq(l,mid),cdq(mid+1,r);// 后序遍历int i=l,j=mid+1,pos=l;for(;j<=r;j++){while(i<=mid && Q[i].y<Q[j].y){update(Q[i].z);// 树状数组维护第三维tmp[pos++]=Q[i++];}/**/// 这里要统计答案tmp[pos++]=Q[j];}for(int k=l;k<i;k++) Clear(Q[k].z);//清空树状数组while(i<=mid) tmp[pos++]=Q[i++];for(int k=l;k<=r;k++)Q[k]=tmp[k];/**/// 若有需要,这里可能也需要统计答案并清空
}signed main()
{/**/// 输入和预处理sort(Q+1,Q+n+1,rule_x);cdq(1,n);// 计算最终答案并输出return 0;
}

给出一个不能用归并版本的题目:序列 - 洛谷

sort 版本

后序遍历版本

就是将原来归并排序的过程用 sort 来硬排序,常数大,一般都不这么写。

例题:陌上花开 - 洛谷

#define mid (l+r>>1)
void CDQ(int l,int r)
{if(l==r) return ;//递归左右 并 按第二维排序CDQ(l,mid);     sort(p+l,p+mid+1,rule_y);CDQ(mid+1,r);   sort(p+mid+1,p+r+1,rule_y);// 按第二维排序后,第一维的顺序虽被打乱// 但由于我们是按 第一维 从小到大的顺序 二分// 所以对于 左半边的任意x 仍然小于 右半边的任意x// 我们计算左半边对右半边贡献的价值时仍满足 第一维的偏序条件//归并左右 双指针计算价值int i=l,j=mid+1;for(;j<=r;j++){while(i<=mid && p[i].y<=p[j].y)//左半边的i 可以 为右半边的 j 在第二维提供价值{update(p[i].z,p[i].cnt);//将i的第三维计入树状数组i++;}p[j].ans+=query(p[j].z);//计算第三维的价值}//清空树状数组for(int k=l;k<i;k++)update(p[k].z,-p[k].cnt);
}

中序遍历版本

一个用于处理有严格统计顺序并且偏序条件关联不同维度的题目,比如典型的 CDQ 分治套 DP 题目 序列 - 洛谷。

struct node
{int p,l,r,x;
}Q[N];#define lowbit(x) ( x&(-x) )
int T[N];inline void update(int x,int val)
{for(;x<=M;x+=lowbit(x))ckmax(T[x],val);
}inline void Clear(int x)
{for(;x<=M;x+=lowbit(x))T[x]=0;
}inline int query(int x)
{int ans=0;for(;x>0;x-=lowbit(x))ckmax(ans,T[x]);return ans;
}bool rule_x(node u,node v)
{ return u.x<v.x; }bool rule_l(node u,node v)
{ return u.l<v.l; }bool rule_p(node u,node v)
{ return u.p<v.p; }void CDQ(int l,int r)
{if(l==r) return ;int mid=l+r>>1;CDQ(l,mid);sort(Q+l,Q+mid+1,rule_x);sort(Q+mid+1,Q+r+1,rule_l);int i=l,j=mid+1;while(j<=r){while(i<=mid && Q[i].x<=Q[j].l){update(Q[i].r,dp[Q[i].p]);i++;}ckmax(dp[Q[j].p],query(Q[j].x)+1);j++;}for(int k=l;k<i;k++) Clear(Q[k].r);sort(Q+l,Q+r+1,rule_p);CDQ(mid+1,r);
}

四维偏序

大体上就是将用一次排序维护第一维,归并处理第二和第三维,用数据结构处理第四维。

http://www.sczhlp.com/news/107097/

相关文章:

  • 【初赛】计算机语言 - Slayer
  • 深入浅出RocketMQ客户端编程
  • 网站改版做301是啥意思 换域名南通做电力的公司网站
  • 企业年金退休后是一次性领取还是按月领取电子商务seo
  • 建设游戏运营网站开展工作总结网站猜你喜欢代码
  • 中国可信网站查询自己的网站发文章怎么做外链
  • 做网站可以用电脑当服务器吗太原做app网站建设
  • linux做网站配置wordpress 控制台 慢
  • 临海网站制作软件开发培训教程
  • 红桥网站建设电子商务营销模式有哪些
  • 网站设计客户案例商城网站怎么做优化
  • Win10玩LOL弹窗
  • 崇文企业网站建设公司北京比较好的互联网公司
  • 怎么给网站做百度优化做网站公司做网站公司
  • 怎么黑网站wordpress 家装装修模板
  • 文化传媒网站建设做网站怎么做呀
  • 海城百度公司 海城网站建设网站的建设时间
  • 网站宣传的手段有哪些?(写出五种以上)软件技术培训机构
  • 9.16 一些记录
  • Week 1 Homework
  • 如何选择网站建设平台学校网站查询学历
  • 公司微网站怎么做的国外高清人像图片素材网站
  • 做网站的像素是多少中国机械加工最多的地方
  • 网页qq空间登录优化网站图片
  • 韩路做的网站是什么名字自己做的娱乐平台网站
  • 梅河口城乡建设网站网页制作平台播放视频
  • 苏小小移动网站手机怎么浏览国外网站
  • 网站开发后台做些什么优秀的建筑设计作品
  • 浙江建站管理系统价格智慧园区官网设计
  • 建设人才库网站企业先做网站还是先做淘宝