CDQ分治入门

简介

CDQ分治是一种特别的分治方法,它由CDQ(陈丹琦)神犇于09国家集训队作业中首次提出,因此得名。CDQ分治属于分治的一种。它一般只能处理非强制在线的问题,除此之外这个算法作为某些复杂算法的替代品几乎是没有缺点的。

深入

对于一个数据结构题而言(或者需要运用数据结构的地方),我们无非就是做两件操作,一是修改,二是查询。

对于修改而言,有插入,删除,变更(其实等价于删除再插入)这几种方式。

那么查询的本质是什么呢?我们思考所遇到过的数据结构题,可以发现查询实际上就在做一件事情:把符合本次查询的限制的修改对答案产生的效果合并起来满足。这种限制通常表现为一种序的要求,并且这种序是广义的,符合限制的操作往往是按某种序(或多种序)排序后的操作的前缀。        通常来说,查询一定有时间上的限制,也就是要求考虑发生在某个时刻之前的所有查询,对于一个问题而言,假如所有查询要求的发生时刻相同,那这就是一个静态查询问题,如果要求发生的时刻随着查询而变,那这就是一个动态修改问题,动态修改问题较静态查询而言复杂很多,往往需要高级数据结构,可持久化等手段,而静态查询简单很多,例如时间倒流,twopointers之类的方法都是很好的选择。

  动态修改->静态查询!

CDQ分治算法的核心就在于:去掉时间的限制,将所有查询要求发生的时刻同化,化动态修改为静态查询(其实对于有些问题来说可以把某一维的限制通过排序看作时间限制然后运用CDQ分治)。

  我们记过程Solve(l,r)表示处理完[l,r]内的修改对查询的影响。此时我们引入分治思想,将操作序列划分为[l,mid],[mid+1,r]两个区间,这两个/区间内部的修改对区间内部的查询的影响是完全相同的/的子问题,我们递归处理,处理完之后剩下来只要考虑[l,mid]中的修改对[mid+1,r]中的查询的影响。这时我们发现这其实已经变成了一个静态查询问题,因为所有的查询都发生在修改之后,我们只需要考虑静态查询的问题如何处理即可。

  具体做法

考虑这样一个问题,有若干询问和若干修改,要求在O(nlogn)时间复杂度内回答所有的询问。(下把询问与修改统称为操作)。

  我们把[l,r]代表当前处理的操作的区间,即处理第l个到第r个操作,先找到区间的中间m=(l+r)/2。

    (1)然后对于前一半[l,m]我们先递归解决。

    (2)对于所有在[l,m]内的修改操作,枚举处理它对于[m,r]内的所有操作影响。

    (3)之后递归处理[m,r]这一区间。

  复杂度分析:分治共有log(n)层,那么要求每一层都在线性的时间复杂度内完成,才能保证总时间复杂度是O(nlogn)。

   对于不同的题目,修改和询问是不一样的。在某些修改之间互相独立的题目下,还可以调换(2)(3)的顺序。

  当然cdq分治也可以像其他的分治方法一样,巧妙利用归并排序,来实现每层O(logn)

接下来我们看道题目帮助理解

Arnooks's Defensive Line [Uva live 5871]

Describe  (不想看英语的请往下跳到一句话题意)

  Based on the latest intelligence reports, Chief Arnook of the northern tribe has become suspicious of the warrior nations that dwell south of the border. The chief has ordered his warriors to protect the southern border which runs parallel to the 54 o latitude line and stretches between the longitudes of 1 o to 1000, 000, 000 o , inclusive.
  Each warrior is assigned the task of protecting a segment of the border defined to lie between longitudes a and b, inclusive. No two warriors are assigned to protect the exact same segment. Bound by loyalty to his chief, a warrior will inform the chief upon his arrival at his appointed post and will never leave once he arrives.
  Your task is to write a program that performs the following two operations + a b a warrior assumes his position and protects the segment between longitudes a and b, inclusive. ? c d computes the number of warriors who completely protect the segment between longitudes c and d, inclusive. The segment between the longitudes c and d, inclusive, is said to be completely protected by a warrior X if and only if warrior X protects a segment between a and b, inclusive, and a ≤ c < d ≤ b. to help Chief Arnook track the status of his border protection.

Input
The input starts with an integer N (1 ≤ N ≤ 500000), on a line by itself, that indicates the number of operations. Each of the following N lines contains one operation. The description of an operation consists of a character ‘+’ or ‘?’ followed by two integers on a line by itself. The entries on a line are separated by single blank spaces.

Output
There is one output line for each input line that starts with the operation ‘?’. The output consists of a single integer that represents the number of warriors who completely protect the corresponding segment at the time.
There is no output for input lines that start with the character ‘+’.

Sample Input
9
+ 5 10
+ 7 20
+ 3 15
? 9 12
+ 10 20
? 8 9
+ 6 30
? 8 9
? 9 12

Sample Output
2
3
4
3

一句话题意

有两种操作(共n个,n<=500000), 一个是插入一个[l,r]的区间,另一个是询问一个区间[l,r],前面有多少个区间完全包含了这个区间。

思路

法一:很容易想到的一个搞法是线段树套平衡树,也就是对于插入的区间,把[1,l]都插入一个r,然后对询问的区间就是看[1,l]里面有多少个数>=r,然而这样的空间复杂度是nlog2n,n=50w显然T飞

法二:换种思路,去掉时间限制,把问题看成一个序列,则前面的修改会对后面的询问造成影响。于是我们便想到了CDQ分治中第二点:对于所有在[l,m]内的修改操作,枚举处理它对于[m,r]内的所有操作影响。”所以我们可以对一个操作序列[a,b], 设m=(a+b)/2,先递归处理[a,m], [m+1,b],然后考虑[a,m]里面的插入区间的操作对[m+1,b]里面询问的影响。也就是转化成静态的问题。可以先把区间按照右端点从大到小排序*,然后扫一边,扫到一个插入区间用树状数组就在l处+1,询问就是原有答案加上sum(l)。

上面*号注意,右端点相同时,左端点一定要从小到大排序,举个例子,如果一个询问是 i+1->j,一个插入是i->j,插入一定要排在询问前面才能被统计到

代码

 1 #include<set>
 2 #include<map>
 3 #include<stack>
 4 #include<queue>
 5 #include<cstdio>
 6 #include<cstring>
 7 #include<iostream>
 8 #include<algorithm>
 9 #define RG register int
10 #define rep(i,a,b)    for(RG i=a;i<=b;i++)
11 #define per(i,a,b)    for(RG i=a;i>=b;i--)
12 #define ll long long
13 #define inf (1<<30)
14 #define maxn 500005
15 #define lowbit(x) (x&(-x))
16 using namespace std;
17 int n,cnt;
18 int hash_table[maxn<<1],t[maxn<<1],ans[maxn];
19 struct Dat{
20     char type;
21     int l,r,id;
22 }dat[maxn];
23 inline int read()
24 {
25     int x=0,f=1;char c=getchar();
26     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
27     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
28     return x*f;
29 }
30
31 int pre()
32 {
33     char c;
34     n=read();
35     rep(i,1,n)
36     {
37         scanf("%c",&c);dat[i].l=hash_table[++cnt]=read(),dat[i].r=hash_table[++cnt]=read(),dat[i].id=i;
38         if(c=='+')    dat[i].type=1;
39     }
40     sort(hash_table+1,hash_table+1+cnt);
41     cnt=unique(hash_table+1,hash_table+1+cnt)-hash_table-1;
42     rep(i,1,n)
43     {
44         dat[i].l=lower_bound(hash_table+1,hash_table+1+cnt,dat[i].l)-hash_table;
45         dat[i].r=lower_bound(hash_table+1,hash_table+1+cnt,dat[i].r)-hash_table;
46     }
47 }
48
49 inline bool cmp(const Dat &a,const Dat &b){return a.r==b.r?a.l<b.l:a.r>b.r;}
50
51 void add(int x,int val)
52 {
53     while(x<=cnt)
54         t[x]+=val,x+=lowbit(x);
55 }
56
57 int query(int x)
58 {
59     int sum=0;
60     while(x)
61         sum+=t[x],x-=lowbit(x);
62     return sum;
63 }
64
65 void CDQ(int l,int r)
66 {
67     if(l==r)    return;
68     int mid=(l+r)>>1;
69     CDQ(l,mid);
70     CDQ(mid+1,r);
71     sort(dat+l,dat+r+1,cmp);
72     for(int i=l;i<=r;i++)
73     {
74         if(dat[i].type&&dat[i].id<=mid)    add(dat[i].l,1);
75         if(!dat[i].type&&dat[i].id>mid)    ans[dat[i].id]+=query(dat[i].l);
76     }
77     for(int i=l;i<=r;i++)
78         if(dat[i].type&&dat[i].id<=mid)    add(dat[i].l,-1);
79 }
80
81 inline bool cnm(const Dat &a,const Dat &b){return a.id<b.id;}
82
83 int main()
84 {
85     pre();
86     CDQ(1,n);
87     sort(dat+1,dat+1+n,cnm);
88     rep(i,1,n)    if(!dat[i].type)    printf("%d\n",ans[i]);
89     return 0;
90 }

View Code

转载于:https://www.cnblogs.com/ibilllee/p/7678685.html

CDQ分治入门 + 例题 Arnooks's Defensive Line [Uva live 5871]相关推荐

  1. UVALive 5871 Arnooks's Defensive Line (cdq分治)

    题意: 有两种操作, 一个是插入一个[l,r]的区间,另一个是询问一个区间[l,r],前面有多少个区间完全包含了这个区间. 思路: 首先离散化.. 很容易想到的一个搞法是线段树套平衡树或者树状数组套平 ...

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

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

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

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

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

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

  5. 点分治+CDQ分治+整体二分全纪录

    点分治 点分治讲解 解决树上路径问题 经典例题:点分治(长度小于m的路径计数) 经典例题:点分治(聪聪可可) 经典例题:点分治(多个定值路径计数) 经典例题:点分治(采药) 经典例题:点分治+ST表+ ...

  6. 三维偏序/cdq分治/

    三维偏序---cdq分治 cdq分治概述 二维偏序概述 二维偏序例题分析 三维偏序概述 例题分析 cdq分治概述 前置知识:(如果不懂要先去了解分治) > 分治: > 分而治之,将原问题不 ...

  7. [学习笔记]CDQ分治

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

  8. BZOJ 2716 [Violet 3]天使玩偶 (CDQ分治、树状数组)

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2716 怎么KD树跑得都那么快啊..我写的CDQ分治被暴虐 做四遍CDQ分治,每次求一个 ...

  9. 二维LIS(CDQ分治)

    题目描述 给定一个长度为N的序列S,S的每个元素pi是一个二元组(xi,yi),定义pi<pj当且仅当xi<xj并且yi<yj,求S的最长上升子序列长度 输入格式 第一行一个N,表示 ...

最新文章

  1. Android调用前置摄像头的方法
  2. USACO_2_1_The Castle
  3. [BUUCTF-pwn]——ciscn_2019_s_3
  4. 建模:确定服务的边界——《微服务设计》读书笔记
  5. python写飞机大战游戏_python实现飞机大战游戏
  6. 公众号文章折叠点击后展开案例_(案例)蜂窝纸板在包装中的应用重型箱
  7. 可能比文档还详细--VueRouter完全指北
  8. tensorflow分布式运行
  9. 【目标检测】SSD中的hard negative mining
  10. 精品LowPoly低多边形风格模型插件资源包合集(随时更新)
  11. 计算机编程教育资源,风变编程以科技实现教育普惠,俱进教育公平
  12. Spring boot 整合Spring Security Jwt
  13. [Setting]win7下运行exe失败:应用程序无法启动,因为应用程序的并行配置不正确
  14. 云服务器如果要挂QQ机器人的话,怎么操作?
  15. 过一下hibernate4-3
  16. 斐迅面试记录—Http协议中的Header
  17. 小灵通退市:生得伟大 死得光荣!
  18. 三分钟彻底禁用、隐藏Android设备底部虚拟按钮(亲测有效)
  19. VLAN的作用 与 基本原理
  20. WinMerge UTF-8 中文乱码

热门文章

  1. 得到-薛兆丰的北大经济学课-4-价格的作用
  2. lay-verify自定义验证
  3. 【老生谈算法】matlab实现非线性整数规划的遗传算法——遗传算法
  4. Github上有趣的100个python项目
  5. 6、阿里云OSS对象存储手把手学习及企业使用方案
  6. 单商户商城系统功能拆解27—营销中心—拼团活动
  7. 武汉高性能计算大会2022举办,高性能计算生态发展再添新动力
  8. android 微信 联系人,android高仿微信联系人选择
  9. 如何成为月薪5W的数据产品经理?
  10. Windows10常用快捷键分享