听娜姐讲完FFT,一脸懵逼,还是来讲讲【CDQ分治】吧。。。

用途:

解决 “带时间轴的更改和查询” 问题。

算法流程:

首先我们要知道,这个算法是离线的,还是利用递归进行求解的。

  1. 把读入的n个操作都按照时间轴排列好。
  2. 把时间轴劈开,分为[l,mid]和[mid+1,r]两部分。
  3. 开始当前层cdq(l,r)的求解前先进行cdq(l,mid)与cdq(mid+1,r)的求解。
  4. 拎出区间[l,mid]内的所有修改操作和区间[mid+1,r]内的所有查询操作[mid+1,r]。
  5. 统计区间[l,mid]内的所有修改操作对区间[mid+1,r]内的所有查询操作的影响,并将影响加入ans数组中。

关于算法的正确性:

为什么这么做会是对的呢?我们不妨举个例子来看看。

加入一共有7个时刻(或者说是个7操作),对于位于3时刻的修改操作,在cdq(1,7)中,统计了它对于区间[5,7]中查询的影响,又在cdq(3,4)中统计了区间[4,4]中查询的影响。

可以看到,对于位于3时刻的查询操作,在我们的cdq过程中,统计了它对于[4,7]的时刻中,所有查询操作的影响。

例题以及题解:

例题:

BOI 2007 【Mokia 摩基亚】     洛谷里有,P4390。

题目概述:

(至于为什么是概述呢?——题目B话太TM多了!!!

给你一个二维平面直角坐标系,还有一些操作。

操作有两种:

1.格式"(1,x,y,w)",表示在(x,y)的地方加上权值w。
2.格式"(2,sx,sy,ex,ey)",表示询问以(sx,sy)为左上角顶点,(ex,ey)为右下角顶点,询问矩形区间内的权值和。

后面的修改操作不会对前面的查询操作产生影响。

数据:操作数<=200000,x,y,sx,sy,ex,ey<=2000000

思路分析:

大家还是先打消要用二维树状数组的念头吧

是二维的,那么我们应该怎么做呢?(先提示下吧,log2的,大家可以先想一想)

滴,滴,滴,滴————————

好,时间到,那就再给大家一个提示吧。

某名Niro**的dalao(他/她 真的是dalao)说过:“CDQ分治就是花log n的时间,把所有的修改操作都移到查询操作之前。”

再想想。。。。。。

(假如说还没有想到的话,可以先看一下下文中那些大号加粗的字,看看有没有思路啥的)

(想到了的话,就可以把这篇博客关掉了,再顺手点个推荐啥的)

嗯,现在就到我讲了吧!

二维的,又不能用二维树状数组,再看看博客标题——“CDQ分治”。

en~~~~~

那就肯定是CDQ分治啦!!!

那么当我们把所有的修改都放在查询后面之后,我们应该怎么做呢?

显然要对问题进行“降维打击”

这个降维打击是个啥呢?——就是把1、2操作(其中把2操作变成起始和结束的两个点)对于x轴进行排序嘛。

排序之后,我们就可以保证在x轴上,前面做过的修改操作,在x轴上是永远包含于后面的查询操作的(如果它的x坐标大于当前查询操作右端点对应的左端点的)。

那么我们只要维护y轴就可以了,这个可以用树状数组来维护。

具体方法的话就是,给树状数组中修改点的y坐标加上它的权值,然后遇到查询操作的右端点时,就统计一下y取值范围内的和就可以了。

那么最后的一个问题就是如果修改点的x坐标小于查询当前查询操作右端点对应的左端点我们应该怎么办呢?

大家先思考一下吧。

......

~~~好了吗?我说喽。——差分嘛!

具体方法就是——遇到左端点时,先把当前树状数组中属于询问范围的y的区间和给减掉嘛。

代码实现:

#include<bits/stdc++.h>
using namespace std;
const int N=200005;
struct point{int x,y,id;
};
point a[N],b[N<<1];
int x[N],y[N],sx[N],sy[N],ex[N],ey[N],w[N],ans[N],c[2000005],acnt,bcnt,tot,opt;
bool cmp (point a,point b){return a.x<b.x;
}
void update(int x,int val){if (x<=2000000) c[x]+=val,update(x+(x&(-x)),val);
}
int query(int x){if (x>0) return c[x]+query(x-(x&(-x))); else return 0;
}
void cdq(int l,int r){if (l==r) return;int mid=l+r>>1; cdq(l,mid); cdq(mid+1,r);acnt=0,bcnt=0;for (int i=l;i<=mid;i++)if (x[i]>0) ++acnt,a[acnt].x=x[i],a[acnt].y=y[i],a[acnt].id=i;for (int i=mid+1;i<=r;i++)if (sx[i]>0) ++bcnt,b[bcnt].x=sx[i]-1,b[bcnt].y=sy[i],b[bcnt].id=i,++bcnt,b[bcnt].x=ex[i],b[bcnt].y=ey[i],b[bcnt].id=i;sort(a+1,a+1+acnt,cmp);sort(b+1,b+1+bcnt,cmp);int i=1,j=1;while (i<=acnt||j<=bcnt)if (j>bcnt||i<=acnt&&a[i].x<=b[j].x) update(a[i].y,w[a[i].id]),++i;else if (b[j].x==sx[b[j].id]-1&&b[j].y==sy[b[j].id]) ans[b[j].id]-=query(ey[b[j].id])-query(b[j].y-1),j++;else ans[b[j].id]+=query(b[j].y)-query(sy[b[j].id]-1),j++;for (int i=l;i<=mid;i++) if (x[i]>0) update(y[i],-w[i]);
}
int main(){scanf("0 %d",&w[0]);scanf("%d",&opt);while (opt!=3){if (opt==1) ++tot,scanf("%d%d%d",&x[tot],&y[tot],&w[tot]);else ++tot,scanf("%d%d%d%d",&sx[tot],&sy[tot],&ex[tot],&ey[tot]);scanf("%d",&opt);}cdq(1,tot);for (int i=1;i<=tot;i++)if (sx[i]>0) printf("%d\n",ans[i]);return 0;
}

转载于:https://www.cnblogs.com/WR-Eternity/p/10079431.html

关于【CDQ分治】的学习相关推荐

  1. 【教程】简易CDQ分治教程学习笔记

    前言 辣鸡蒟蒻__stdcall终于会CDQ分治啦!       CDQ分治是我们处理各类问题的重要武器.它的优势在于可以顶替复杂的高级数据结构,而且常数比较小:缺点在于必须离线操作. CDQ分治的基 ...

  2. [偏序关系与CDQ分治]【学习笔记】

    组合数学真是太棒了 $CDQ$真是太棒了(雾 参考资料: 1.<组合数学> 2.论文 课件 很容易查到 3.sro __stdcall 偏序关系 关系: 集合$X$上的关系是$X$与$X$ ...

  3. 简单入门CDQ分治(很有意思的算法)

    最近因为牛客暑期多校的一道题涉及到了CDQ分治,于是便去学习了一下CDQ分治. CDQ分治是以曾经的IOI选手陈丹琦命名的一种强大的算法,主要用于解决偏序问题,通过对一维进行排序(在这里说的总维度为二 ...

  4. [学习笔记]CDQ分治

    分治,考虑前一半对后一半的影响. (和一般分治不太相同的思想是,一般分治不分谁对谁的影响,跨mid的都要统计.(全局变量统计) 而CDQ貌似要落脚到前一半对后一半的影响上,也就是贡献在后一半统计,由前 ...

  5. 【cdq分治】cdq分治与整体二分学习笔记Part2.cdq分治

    上午的学习学会了整体二分,下午学了cdq分治 发现了二者的区别: 整体二分的主体是在不断地二分答案(把所有询问二分),而cdq分治则是在不断地二分操作. 当然同样的,cdq分治的复杂度也是与区间长度正 ...

  6. 【cdq分治】cdq分治与整体二分学习笔记Part1.整体二分

    之所以把cdq分治和整体二分放在一起学习,是因为他们两个实在太像了-不管是做法还是代码- 感觉整体二分可能会比cdq分治稍微简单那么一点点?所以先学整体二分. 整体二分是对答案进行二分,其具体操作如下 ...

  7. CDQ分治学习及例题总结

    文章目录 1.**使用cdq分治的条件:** 2.**cdq分治的性质:** 3. **cdq使用步骤:** 4.**自己对cdq分治学习的一些感悟:** 5. cdq分治的详细讲解(转自[stdca ...

  8. [摸鱼]cdq分治 学习笔记

    待我玩会游戏整理下思绪(分明是想摸鱼 cdq分治是一种用于降维和处理对不同子区间有贡献的离线分治算法 对于常见的操作查询题目而言,时间总是有序的,而cdq分治则是耗费\(O(logq)\)的代价使动态 ...

  9. 学习笔记——CDQ分治

    再次感谢这位大佬的博客:https://www.cnblogs.com/ljc20020730/p/10395866.html CDQ分治,是一种在分治合并中计算前面值对后面答案的贡献的一种算法.今天 ...

  10. cdq分治 学习笔记

    什么是 c d q cdq cdq 分治 一种很优美的分治,具体来说,我们解决 [ l , r ] [l,r] [l,r] 这个,跟普通的分治大体思路一样,也是先分治 [ l , m i d ] [l ...

最新文章

  1. 大专python工资有多高-最新 | 2019年Python工程师的平均薪资是多少?
  2. boost::geometry::model::segment用法的测试程序
  3. linux7自带haprox版本,CentOS7.4—构建最新版haproxy高可用群集
  4. 欢迎光临CAX软件二次开发开源社区!
  5. ssl1613-最短路径问题【图论,最短路径(还不明显?)】
  6. java中原始数据文件的输入
  7. java已被弱化签名,高效Java第四十条建议:谨慎设计方法签名
  8. Hi3559AV100开发环境搭建
  9. [转]Hibernate不能自动建表解决办法及Hibernate不同数据库的连接及SQL方言
  10. win64 oracle下载,oracle 11g 64位下载
  11. 2021年N1叉车司机最新解析及N1叉车司机模拟考试
  12. 康托尔三分集是不可列集的证明
  13. 窃钩者诛,“窃脸”者___?
  14. element ui 使用导航unique-opened问题
  15. Selenium||解决给元素输入文本失败问题
  16. 夕阳美,美到骨子里了
  17. 2020北大信科计算机考研公示,2020年北京大学信息科学技术学院硕士研究生拟录取名单.pdf...
  18. 多项式乘积求极值点与拐点“比较快速”的方法:沉鱼落雁闭月羞花
  19. linux查看网络信息命令
  20. 使用 x32dbg 分析 PC 上 QQ 撤销功能(好友消息和群消息)

热门文章

  1. argparse模块用法
  2. 博文视点云原生书单丨释放云原生技术红利
  3. 数据需求有多野?“三连问”帮你处理得明明白白
  4. 聊聊手游的那些惊喜与惊吓
  5. Android中的界面组成
  6. 网站运营之比较和差异化
  7. matlab信息量估计法估计嵌入率,LSB密写分析-信息量估计法
  8. java检测栈溢出_java运行方法栈溢出
  9. Linux防火墙连续多个端口,Linux防火墙iptables配置开放某个端口
  10. Flutter高级第5篇:官方推荐的状态管理库 provider 的使用