偏序问题及CDQ分治详解
CDQ用来解决分治时左半部分对右半部分造成影响的问题。
CDQ分治的经典问题是三维偏序问题。
要想解决三维偏序问题,首先你要知道什么是偏序。(废话)
一维偏序:
给出直线上的n个点,问有多少对点满足xi<=xj
对于这个问题,直接排序就可以了。
二维偏序:
给定平面内的n个点,问有多少对点满足xi<=xj且yi<=yj
这是个经典的树状数组问题,相信学过树状数组的人一定都做过·一道叫做数星星的题,这道题就是经典的二维偏序问题,并不需要二维数组,我们可以通过按x坐标为第一关键字排序,从而消除x坐标给答案带来的影响。然后我们用一个树状数组维护前缀和,记录之前有多少点的y坐标比该点小,由于在之前的x坐标一定比较小,因此只要保证y坐标即可。
三维偏序:
给出空间内的n个点,问有多少点对满足xi<=xj且yi<=yj且zi<=zj
树套树???码量++,空间++
在不强制在线的情况下,我们完全可以使用CDQ分治这种东西来简化一层树结构,因此三维偏序问题实际上可以这样处理:
1)仿照二位偏序问题,先给x排序,消除其影响。
2)使用CDQ分治,消除y的影响
3)使用数组维护z的前缀,统计答案。
1)、3)都是二维偏序的正常步骤,下面重点来讲讲CDQ分治
前边已经讲过了,CDQ分治要处理左区间对右区间的贡献问题。
其实很简单,我们把每一步操作分成三步:
1)递归处理左区间;2)递归处理右区间;3)处理左区间对右区间的贡献。
在三维偏序问题中,之所以不考虑右区间对左区间的贡献,是因为按x排序了,因此右区间一定不会对左区间造成贡献。
然后我们直接就按y排序,然后看一个东西是在左区间还是右区间,是左区间就放进一个树状数组中,否则直接求贡献。
因为CDQ直接分治到最小的单位,也就是一个点,因此可以保证所有答案都是没有遗漏的。
为了保证答案的不重复性,我们可以在求完贡献后把树状数组内贡献再撤消;
例题:洛谷P3810:陌上花开
参考代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#define N 500005
#define lowbit(x) x&-x
using namespace std;
int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=(x<<)+(x<<)+(ch^);ch=getchar();}
return x*f;
}
struct node{int x,y,z,id;}a[N];
bool cmpa(node a,node b)
{
if(a.x!=b.x)return a.x<b.x;
if(a.y!=b.y)return a.y<b.y;
return a.z<b.z;
}
bool cmpb(node a,node b)
{
if(a.y!=b.y)return a.y<b.y;
if(a.x!=b.x)return a.x<b.x;
return a.z<b.z;
}
int n,k,tot,c[],b[],f[],s,j,block[];
void modify(int x,int m){for(;x<=k;x+=lowbit(x))c[x]+=m;}
int query(int x){int res=;for(;x;x-=lowbit(x))res+=c[x];return res;}
void cdq(int l,int r)
{
if(l==r)return;
int mid=(l+r)/;
cdq(l,mid);cdq(mid+,r);
sort(a+l,a+r+,cmpb);
for(int i=l;i<=r;i++)(a[i].x<=mid)?modify(a[i].z,),s=:b[a[i].id]+=query(a[i].z);
for(int i=l;i<=r;i++)if(a[i].x<=mid)modify(a[i].z,-);
}
int main()
{
ios::sync_with_stdio();cin.tie();cout.tie();
cin>>n>>k;//n=read();k=read();
for(int i=;i<=n;i++)
{
cin>>a[i].x>>a[i].y>>a[i].z;//=read();a[i].y=read();a[i].z=read();
a[i].id=i;
}
sort(a+,a++n,cmpa);
for(int i=;i<=n;)
{
j=i+;
while(j<=n&&a[i].x==a[j].x&&a[i].y==a[j].y&&a[i].z==a[j].z)j++;
while(i<j)block[a[i].id]=a[j-].id,i++;
}
for(int i=;i<=n;i++)a[i].x=i;
cdq(,n);
for(int i=;i<=n;i++)f[b[block[a[i].id]]]++;
for(int i=;i<n;i++)printf("%d\n",f[i]);
return ;
}
三位偏序模板代码
偏序问题及CDQ分治详解的更多相关文章
- BZOJ3262陌上花开(三维偏序问题(CDQ分治+树状数组))+CDQ分治基本思想
emmmm我能怎么说呢 CDQ分治显然我没法写一篇完整的优秀的博客,因为我自己还不是很明白... 因为这玩意的思想实在是太短了: fateice如是说道: 如果说对于一道题目的离线操作,假设有n个操作 ...
- 陌上花开(三维偏序)(cdq分治)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3262 其实就是三位偏序的模板,cdq分治入门题. 学习cdq分治请看__stdcall大 ...
- cdq分治略解
前言 陌上花开,可缓缓归矣 --吴越王 寓意:意思是:田间阡陌上的花开了,你可以一边赏花,一边慢慢回来. 隐意:春天都到了,你怎么还没有回来.形容吴越王 ...
- 【CJOJ2375】 【HZOI 2015】偏序 II(cdq分治,树状数组)
传送门 CJOJ Solution 具体实现参考上一篇Blog(四维偏序) 代码实现1(cdq+cdq+cdq+BIT) /* mail: mleautomaton@foxmail.com autho ...
- 【CJOJ2616】 【HZOI 2016】偏序 I(cdq分治,树状数组)
传送门 CJOJ Solution 考虑这是一个四维偏序对吧. 直接cdq套在一起,然后这题有两种实现方法(树状数组的更快!) 代码实现1(cdq+cdq+cdq) /* mail: mleautom ...
- 分治法:三维偏序问题之CDQ分治
我怀疑那个k是用来定界限用的 #include <cstdio> #include <cstring> #include <algorithm> using nam ...
- 『cdq分治和多维偏序问题』
更新了三维偏序问题的拓展 cdq分治 \(cdq\)分治是一种由\(IOI\ Au\)选手\(cdq\)提出的离线分治算法,又称基于时间的分治算法. 二维偏序问题 这是\(cdq\)分治最早提出的时候 ...
- 【BZOJ2141】排队(CDQ分治)
[BZOJ2141]排队(CDQ分治) 题面 题面以及树套树做法见这里 题解 大部分树套树/主席树这类题目都可以用整体二分/CDQ分治来做. 这题考虑一下,在不考虑修改的情况下 贡献是如何产生的? 我 ...
- 并不对劲的cdq分治解三维偏序
为了反驳隔壁很对劲的太刀流,并不对劲的片手流决定与之针锋相对,先一步发表cdq分治解三维偏序. 很对劲的太刀流在这里-> 参照一.二维偏序的方法,会发现一位偏序就是直接排序,可以看成通过排序使 ...
随机推荐
- 获取sender进程所产生的trace文件
直接开启数据库实例级别的sql_trace是不现实的,会对所有连接到oracle的session都产生sql_trace,这样会产生大量的trace文件(垃圾文件),因此为跟踪特定进程的sql信息,可 ...
- python-第三方包的安装和升级和卸载
安装源: 豆瓣 http://pypi.douban.com/simple/ 本地安装: egg文件: 使用settools自带的安装脚本easy_install进行安装 whl文件: ...
- day4 切片,数据类型
day5: 序列,可以使用切片 序列类型:字符串,列表,元祖 特点:可以通过坐标来取值,坐标从0开始 >>> s = "agfdagsgsdgsa" >&g ...
- 对Nuxt的研究
Nuxt就是基于Vue的一个应用框架,采用服务端渲染,让你的SPA应用(Vue)也可以拥有SEO Nuxt的生命周期有些在服务端(Node),客户端,甚至两边都在: 1.其他之前都不存在Window对 ...
- 一天久坐办公室,怎么减fei?!
久坐的危害想必看到这篇文章的,一定都百度浏览了好多文章了,所以危害大家也都知道了,这里也就不一一列出. 久坐有危害,那么怎么减少危害呢,办法是什么???那就是不久坐啦.可是因为工作性质,不久坐臣妾恐怕 ...
- mysql Update语句 语法
mysql Update语句 语法 作用:用于修改表中的数据.广州大理石机械构件 语法:UPDATE 表名称 SET 列名称 = 新值 WHERE 列名称 = 某值 mysql Update语句 示例 ...
- luogu 2491 [SDOI2011]消防 / 1099 树网的核 单调队列 + 树上问题
Code: #include<bits/stdc++.h> #define ll long long #define maxn 300001 #define inf 1000000000 ...
- RabbitMQ消费端ACK与重回队列机制,TTL,死信队列详解(十一)
消费端的手工ACK和NACK 消费端进行消费的时候,如果由于业务异常我们可以进行日志的记录,然后进行补偿. 如果由于服务器宕机等严重问题,那么我们就需要手工进行ACK保障消费端成功. 消费端重回队列 ...
- Mapreduce报错:Split metadata size exceeded 10000000
报错信息: Failure Info:Job initialization failed: java.io.IOException: Split metadata size exceeded 1000 ...
- win7x64 串口程序无法运行,提示:component 'MSCOMM32.OCX' or one of its dependencies not correctlu registered。。。
VB写的串口工具在win7 x64机器运行时遇到的问题, component 'MSCOMM32.OCX' or one of its dependencies not correctlu regis ...