偏序问题及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分治解三维偏序. 很对劲的太刀流在这里-> 参照一.二维偏序的方法,会发现一位偏序就是直接排序,可以看成通过排序使 ...
随机推荐
- MySQL/mariadb知识点总结
1.mysql/mariadb知识点总结:事务相关概念(事务总结-1) http://www.zsythink.net/archives/1204 2.mysql/mariadb知识点总结:事务控制语 ...
- MongoDB之自动启动服务
安装详细步骤请点我 为了能让NoSQLBooster for MongoDB连接的时候不报错,将mongodb添加到系统服务中. 在C:\Program Files\MongoDB\Server\3. ...
- 【leetcode】827. Making A Large Island
题目如下: 解题思路:这个题目可以进行拆分成几个子问题.第一,求出island的数量,其实就是 200. Number of Islands,这个很简单,DFS或者BFS都能搞定:第二,除了求出isl ...
- AngualJS-leaflet之视图等级缩放
在http://tombatossals.github.io/angular-leaflet-directive/#!/examples/events 中的则是zoomlevelschange,然后识 ...
- IIS部署复盘(杂记)
首先,230是网站服务器,231主要放到是数据库:所以在230(部署的服务器)上部署不需要部署IIS和Oracle数据库, 231呢?231是数据库服务器:百度一下数据库服务器是什么? 文档第五步: ...
- Jion的应用
- C#删除文件夹的文件
using System.IO; //判断文件是不是存在if(File.Exists(@"文件路径")){//如果存在则删除File.Delete(@"文件路径" ...
- JSP上传一个文件夹
javaweb上传文件 上传文件的jsp中的部分 上传文件同样可以使用form表单向后端发请求,也可以使用 ajax向后端发请求 1.通过form表单向后端发送请求 <form id=" ...
- Quartus_II官方教程-中文版之SignalTap II
非常实用 187-196 第十二章:调试 Quartus_II官方教程-中文版.pdf
- win php composer安装
composer安装文件下载 https://getcomposer.org/Composer-Setup.exe composer安装: 选择php.exe D:\phpStudy\php55n\p ...