cdq分治解决三维偏序
问题背景
在三维坐标系中有n个点,坐标为(xi,yi,zi). 定义一个点A比一个点B小,当且仅当xA<=xB,yA<=yB,zA<=zB。问对于每个点,有多少个点比它小。(n<=1e5)
其实就是离散数学里的偏序的概念啦,只不过是到了三维。回顾一下偏序的概念:
偏序关系:自反,反对称且传递,符号<
然后先考虑一下二维偏序吧。可以用最长上升子序列LIS来做,然后我们今天讨论一种特殊分治的做法,这种算法是由08年集训队的陈丹琦提出来的,因此叫cdq分治。
主要思想就是先按照第一维排序。然后遍历每一个点,此时我们要统计的就是前面的点中比这个点的y坐标要小的点的个数。我们用一个树状数组来维护y坐标这个信息,于是就只要得到getsum(y)就行了。
三维的CDQ分治呢,做法如下:
第一维排序,第二维CDQ分治,第三维树状数组。
第一维比如先按照x坐标排序。在第二维的CDQ分治时,我们对每一个自区间,先按照y排序,计算左边对右边的影响的时候:
左边的x都小于右边
在每一边y也是依次递增的
我们只要扫描右边,把左边y小于等于当前的y坐标的z坐标更新到树状数组,统计目前树状数组z坐标小于自己的就是偏序<的点的个数。
复杂度分析
根据主定理:
T(n)=2T(n2)+O(kn)=O(knlogn)T(n)=2T(n2)+O(kn)=O(knlogn)
T(n)=2T(n2)+O(knlogn)=O(knlog2 n)
例题
BZOJ 3262 陌上花开
后面这个题虽然是个裸三维偏序,不过也可以转化成三个二维偏序。
另附一个BZOJ3262的别人的代码,可做模板。
//bzoj 3262
//1维排序,二维分治,3维树状数组
#include <bits/stdc++.h>
using namespace std;
const int maxn = 200005;
int n, m, ans[maxn], tree[maxn*4];
struct node{
int a, b, c, s, ans; //s处理相同连续,ans比当前美丽值小个数
node(){}
node(int a, int b, int c, int s, int ans) : a(a), b(b), c(c), s(s), ans(ans) {}
bool operator < (const node &rhs) const{ //按y排序
if(b == rhs.b) return c < rhs.c;
return b < rhs.b;
}
}a[maxn], p[maxn];
bool cmp(node x, node y){ //按照x排序
if(x.a == y.a && x.b == y.b) return x.c < y.c;
if(x.a == y.a) return x.b < y.b;
return x.a < y.a;
}
namespace BIT{
inline int lowbit(int x) {return x&-x;}
inline void update(int x, int y){for(int i = x; i <= m; i+=lowbit(i)) tree[i] += y;}
inline int query(int x){int res = 0; for(int i = x; i; i -= lowbit(i)) res += tree[i]; return res;}
}
using namespace BIT;
void CDQ(int l, int r)
{
if(l == r) return;
int mid = (l + r) >> 1;
CDQ(l, mid);
CDQ(mid+1, r);
sort(p + l, p + mid + 1);
sort(p + mid + 1, p + r + 1);
int i = l, j = mid + 1;
while(j <= r){
while(i <= mid && p[i].b <= p[j].b){
update(p[i].c, p[i].s);
i++;
}
p[j].ans += query(p[j].c);
j++;
}
for(int j = l; j < i; j++) update(p[j].c, -p[j].s);
}
int main(){
int nn;
scanf("%d%d", &nn, &m);
for(int i = 1; i <= nn; i++){
scanf("%d%d%d", &a[i].a, &a[i].b, &a[i].c);
}
sort(a + 1, a + nn + 1, cmp); //按照x排
int cnt = 0; //unique
for(int i = 1; i <= nn; i++){
cnt++;
if(a[i].a != a[i+1].a || a[i].b != a[i+1].b || a[i].c != a[i+1].c){
p[++n] = a[i];
p[n].s = cnt;
cnt = 0;
}
}
CDQ(1, n);
for(int i = 1; i <= n; i++){
ans[p[i].ans + p[i].s - 1] += p[i].s;
}
for(int i = 0; i < nn; i++){
printf("%d\n", ans[i]);
}
return 0;
}
总结
从二维偏序出发,了解了三维偏序的CDQ分治做法。
在这类问题中通常将时间(操作序列)作为第一维,剩下的二维问题使用CDQ分治和数据结构。
这种问题也可以用树套树做,据说很烦,树状数组套个什么Treap啥的,总之比这个CDQ要难写很多。
*:first-child {
margin-top: 0 !important;
}
.markdown-body>*:last-child {
margin-bottom: 0 !important;
}
.markdown-body .anchor {
position: absolute;
top: 0;
bottom: 0;
left: 0;
display: block;
padding-right: 6px;
padding-left: 30px;
margin-left: -30px;
}
.markdown-body .anchor:focus {
outline: none;
}
.markdown-body h1,
.markdown-body h2,
.markdown-body h3,
.markdown-body h4,
.markdown-body h5,
.markdown-body h6 {
position: relative;
margin-top: 1em;
margin-bottom: 16px;
font-weight: bold;
line-height: 1.4;
}
.markdown-body h1 .octicon-link,
.markdown-body h2 .octicon-link,
.markdown-body h3 .octicon-link,
.markdown-body h4 .octicon-link,
.markdown-body h5 .octicon-link,
.markdown-body h6 .octicon-link {
display: none;
color: #000;
vertical-align: middle;
}
.markdown-body h1:hover .anchor,
.markdown-body h2:hover .anchor,
.markdown-body h3:hover .anchor,
.markdown-body h4:hover .anchor,
.markdown-body h5:hover .anchor,
.markdown-body h6:hover .anchor {
height: 1em;
padding-left: 8px;
margin-left: -30px;
line-height: 1;
text-decoration: none;
}
.markdown-body h1:hover .anchor .octicon-link,
.markdown-body h2:hover .anchor .octicon-link,
.markdown-body h3:hover .anchor .octicon-link,
.markdown-body h4:hover .anchor .octicon-link,
.markdown-body h5:hover .anchor .octicon-link,
.markdown-body h6:hover .anchor .octicon-link {
display: inline-block;
}
.markdown-body h1 {
padding-bottom: 0.3em;
font-size: 2.25em;
line-height: 1.2;
border-bottom: 1px solid #eee;
}
.markdown-body h2 {
padding-bottom: 0.3em;
font-size: 1.75em;
line-height: 1.225;
border-bottom: 1px solid #eee;
}
.markdown-body h3 {
font-size: 1.5em;
line-height: 1.43;
}
.markdown-body h4 {
font-size: 1.25em;
}
.markdown-body h5 {
font-size: 1em;
}
.markdown-body h6 {
font-size: 1em;
color: #777;
}
.markdown-body p,
.markdown-body blockquote,
.markdown-body ul,
.markdown-body ol,
.markdown-body dl,
.markdown-body table,
.markdown-body pre {
margin-top: 0;
margin-bottom: 16px;
}
.markdown-body hr {
height: 4px;
padding: 0;
margin: 16px 0;
background-color: #e7e7e7;
border: 0 none;
}
.markdown-body ul,
.markdown-body ol {
padding-left: 2em;
}
.markdown-body ul ul,
.markdown-body ul ol,
.markdown-body ol ol,
.markdown-body ol ul {
margin-top: 0;
margin-bottom: 0;
}
.markdown-body li>p {
margin-top: 16px;
}
.markdown-body dl {
padding: 0;
}
.markdown-body dl dt {
padding: 0;
margin-top: 16px;
font-size: 1em;
font-style: italic;
font-weight: bold;
}
.markdown-body dl dd {
padding: 0 16px;
margin-bottom: 16px;
}
.markdown-body blockquote {
padding: 0 15px;
color: #777;
border-left: 4px solid #ddd;
}
.markdown-body blockquote>:first-child {
margin-top: 0;
}
.markdown-body blockquote>:last-child {
margin-bottom: 0;
}
.markdown-body table {
display: block;
width: 100%;
overflow: auto;
word-break: normal;
word-break: keep-all;
}
.markdown-body table th {
font-weight: bold;
}
.markdown-body table th,
.markdown-body table td {
padding: 6px 13px;
border: 1px solid #ddd;
}
.markdown-body table tr {
background-color: #fff;
border-top: 1px solid #ccc;
}
.markdown-body table tr:nth-child(2n) {
background-color: #f8f8f8;
}
.markdown-body img {
max-width: 100%;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.markdown-body code {
padding: 0;
padding-top: 0.2em;
padding-bottom: 0.2em;
margin: 0;
font-size: 85%;
background-color: rgba(0,0,0,0.04);
border-radius: 3px;
}
.markdown-body code:before,
.markdown-body code:after {
letter-spacing: -0.2em;
content: "\00a0";
}
.markdown-body pre>code {
padding: 0;
margin: 0;
font-size: 100%;
word-break: normal;
white-space: pre;
background: transparent;
border: 0;
}
.markdown-body .highlight {
margin-bottom: 16px;
}
.markdown-body .highlight pre,
.markdown-body pre {
padding: 16px;
overflow: auto;
font-size: 85%;
line-height: 1.45;
background-color: #f7f7f7;
border-radius: 3px;
}
.markdown-body .highlight pre {
margin-bottom: 0;
word-break: normal;
}
.markdown-body pre {
word-wrap: normal;
}
.markdown-body pre code {
display: inline;
max-width: initial;
padding: 0;
margin: 0;
overflow: initial;
line-height: inherit;
word-wrap: normal;
background-color: transparent;
border: 0;
}
.markdown-body pre code:before,
.markdown-body pre code:after {
content: normal;
}
.markdown-body .highlight {
background: #fff;
}
.markdown-body .highlight .mf,
.markdown-body .highlight .mh,
.markdown-body .highlight .mi,
.markdown-body .highlight .mo,
.markdown-body .highlight .il,
.markdown-body .highlight .m {
color: #945277;
}
.markdown-body .highlight .s,
.markdown-body .highlight .sb,
.markdown-body .highlight .sc,
.markdown-body .highlight .sd,
.markdown-body .highlight .s2,
.markdown-body .highlight .se,
.markdown-body .highlight .sh,
.markdown-body .highlight .si,
.markdown-body .highlight .sx,
.markdown-body .highlight .s1 {
color: #df5000;
}
.markdown-body .highlight .kc,
.markdown-body .highlight .kd,
.markdown-body .highlight .kn,
.markdown-body .highlight .kp,
.markdown-body .highlight .kr,
.markdown-body .highlight .kt,
.markdown-body .highlight .k,
.markdown-body .highlight .o {
font-weight: bold;
}
.markdown-body .highlight .kt {
color: #458;
}
.markdown-body .highlight .c,
.markdown-body .highlight .cm,
.markdown-body .highlight .c1 {
color: #998;
font-style: italic;
}
.markdown-body .highlight .cp,
.markdown-body .highlight .cs {
color: #999;
font-weight: bold;
}
.markdown-body .highlight .cs {
font-style: italic;
}
.markdown-body .highlight .n {
color: #333;
}
.markdown-body .highlight .na,
.markdown-body .highlight .nv,
.markdown-body .highlight .vc,
.markdown-body .highlight .vg,
.markdown-body .highlight .vi {
color: #008080;
}
.markdown-body .highlight .nb {
color: #0086B3;
}
.markdown-body .highlight .nc {
color: #458;
font-weight: bold;
}
.markdown-body .highlight .no {
color: #094e99;
}
.markdown-body .highlight .ni {
color: #800080;
}
.markdown-body .highlight .ne {
color: #990000;
font-weight: bold;
}
.markdown-body .highlight .nf {
color: #945277;
font-weight: bold;
}
.markdown-body .highlight .nn {
color: #555;
}
.markdown-body .highlight .nt {
color: #000080;
}
.markdown-body .highlight .err {
color: #a61717;
background-color: #e3d2d2;
}
.markdown-body .highlight .gd {
color: #000;
background-color: #fdd;
}
.markdown-body .highlight .gd .x {
color: #000;
background-color: #faa;
}
.markdown-body .highlight .ge {
font-style: italic;
}
.markdown-body .highlight .gr {
color: #aa0000;
}
.markdown-body .highlight .gh {
color: #999;
}
.markdown-body .highlight .gi {
color: #000;
background-color: #dfd;
}
.markdown-body .highlight .gi .x {
color: #000;
background-color: #afa;
}
.markdown-body .highlight .go {
color: #888;
}
.markdown-body .highlight .gp {
color: #555;
}
.markdown-body .highlight .gs {
font-weight: bold;
}
.markdown-body .highlight .gu {
color: #800080;
font-weight: bold;
}
.markdown-body .highlight .gt {
color: #aa0000;
}
.markdown-body .highlight .ow {
font-weight: bold;
}
.markdown-body .highlight .w {
color: #bbb;
}
.markdown-body .highlight .sr {
color: #017936;
}
.markdown-body .highlight .ss {
color: #8b467f;
}
.markdown-body .highlight .bp {
color: #999;
}
.markdown-body .highlight .gc {
color: #999;
background-color: #EAF2F5;
}
.markdown-body .octicon {
font: normal normal 16px octicons-anchor;
line-height: 1;
display: inline-block;
text-decoration: none;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.markdown-body .octicon-link:before {
content: '\f05c';
}
.markdown-body .task-list-item {
list-style-type: none;
}
.markdown-body .task-list-item+.task-list-item {
margin-top: 3px;
}
.markdown-body .task-list-item input {
float: left;
margin: 0.3em 0 0.25em -1.6em;
vertical-align: middle;
}
/*
github.com style (c) Vasily Polovnyov
*/
.hljs {
display: block;
overflow-x: auto;
padding: 0.5em;
color: #333;
background: #f8f8f8;
-webkit-text-size-adjust: none;
}
.hljs-comment,
.diff .hljs-header {
color: #998;
font-style: italic;
}
.hljs-keyword,
.css .rule .hljs-keyword,
.hljs-winutils,
.nginx .hljs-title,
.hljs-subst,
.hljs-request,
.hljs-status {
color: #333;
font-weight: bold;
}
.hljs-number,
.hljs-hexcolor,
.ruby .hljs-constant {
color: #008080;
}
.hljs-string,
.hljs-tag .hljs-value,
.hljs-doctag,
.tex .hljs-formula {
color: #d14;
}
.hljs-title,
.hljs-id,
.scss .hljs-preprocessor {
color: #900;
font-weight: bold;
}
.hljs-list .hljs-keyword,
.hljs-subst {
font-weight: normal;
}
.hljs-class .hljs-title,
.hljs-type,
.vhdl .hljs-literal,
.tex .hljs-command {
color: #458;
font-weight: bold;
}
.hljs-tag,
.hljs-tag .hljs-title,
.hljs-rule .hljs-property,
.django .hljs-tag .hljs-keyword {
color: #000080;
font-weight: normal;
}
.hljs-attribute,
.hljs-variable,
.lisp .hljs-body,
.hljs-name {
color: #008080;
}
.hljs-regexp {
color: #009926;
}
.hljs-symbol,
.ruby .hljs-symbol .hljs-string,
.lisp .hljs-keyword,
.clojure .hljs-keyword,
.scheme .hljs-keyword,
.tex .hljs-special,
.hljs-prompt {
color: #990073;
}
.hljs-built_in {
color: #0086b3;
}
.hljs-preprocessor,
.hljs-pragma,
.hljs-pi,
.hljs-doctype,
.hljs-shebang,
.hljs-cdata {
color: #999;
font-weight: bold;
}
.hljs-deletion {
background: #fdd;
}
.hljs-addition {
background: #dfd;
}
.diff .hljs-change {
background: #0086b3;
}
.hljs-chunk {
color: #aaa;
}
-->
cdq分治解决三维偏序的更多相关文章
- 并不对劲的cdq分治解三维偏序
为了反驳隔壁很对劲的太刀流,并不对劲的片手流决定与之针锋相对,先一步发表cdq分治解三维偏序. 很对劲的太刀流在这里-> 参照一.二维偏序的方法,会发现一位偏序就是直接排序,可以看成通过排序使 ...
- 【算法学习】【洛谷】cdq分治 & P3810 三维偏序
cdq是何许人也?请参看这篇:https://wenku.baidu.com/view/3b913556fd0a79563d1e7245.html. 在这篇论文中,cdq提出了对修改/询问型问题(Mo ...
- hdu5618(cdq分治求三维偏序)
题意:给n(n<=100000)个点,坐标为(xi,yi,zi)(1<=xi,yi,zi<=100000),定义一个点A比一个点B小,当且仅当xA<=xB,yA<=yB, ...
- SPOJ:Another Longest Increasing Subsequence Problem(CDQ分治求三维偏序)
Given a sequence of N pairs of integers, find the length of the longest increasing subsequence of it ...
- BZOJ 3262: 陌上花开 (cdq分治,三维偏序)
#include <iostream> #include <stdio.h> #include <algorithm> using namespace std; c ...
- P3157 [CQOI2011]动态逆序对 (CDQ解决三维偏序问题)
P3157 [CQOI2011]动态逆序对 题目描述 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任 ...
- [用CDQ分治解决区间加&区间求和]【习作】
[前言] 作为一个什么数据结构都不会只会CDQ分治和分块的蒟蒻,面对区间加&区间求和这么难的问题,怎么可能会写线段树呢 于是,用CDQ分治解决区间加&区间求和这篇习作应运而生 [Par ...
- HDU4742 CDQ分治,三维LIS
HDU4742 CDQ分治,三维LIS 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4742 题意: 每个球都有三个属性值x,y,z,要求最长的lis的 ...
- P4390 [BOI2007]Mokia 摩基亚 (CDQ解决三维偏序问题)
题目描述 摩尔瓦多的移动电话公司摩基亚(Mokia)设计出了一种新的用户定位系统.和其他的定位系统一样,它能够迅速回答任何形如"用户C的位置在哪?"的问题,精确到毫米.但其真正高科 ...
随机推荐
- HTTP协议请求方式: 中GET、POST和HEAD的介绍_孤帆一叶
HTTP协议中GET.POST和HEAD的介绍 2008-05-10 14:15 GET: 请求指定的页面信息,并返回实体主体.HEAD: 只请求页面的首部.POST: 请求服务器接受所指定的文档作为 ...
- 发行版Linux和麒麟操作系统下netperf 网络性能测试
Netperf是一种网络性能的测量工具,主要针对基于TCP或UDP的传输.Netperf根据应用的不同,可以进行不同模式的网络性能测试,即批量数据传输(bulk data transfer)模式和请求 ...
- gettimeofday()函数来得到时间
gettimeofday()函数的使用方法: 1.简介: 在C语言中可以使用函数gettimeofday()函数来得到时间.它的精度可以达到微妙 2.函数原型: #include<sys/tim ...
- Ubuntu16.04 kaldi的简单配置
1.什么是kaldi kaldi是使用c++写的语音识别的工具,apache 授予了v2.0的证书(果真应验,apache旗下无弱将).kaldi旨在供语音识别研究员使用.kaldi在目标和范围上和H ...
- JAVA 第二周学习总结
20175308 2018-2019-2 <Java程序设计>第二周学习总结 教材学习内容总结: 第二章学习内容: 1.认识标识符与关键字 2.java的八种数据类型,着重记好精度由高到低 ...
- python中安装Tensorflow
执行命令:pip install --upgrade tensorflow 即可.
- 翻译 | The Principles of OOD 面向对象设计原则
本文首发于vivo互联网技术微信公众号 https://mp.weixin.qq.com/s/Q_pziBUhKRywafKeY2T7YQ 作者:Robert C. Martin 翻译:张硕 本文由来 ...
- 20155301 Exp4 恶意代码分析
20155301 Exp4 恶意代码分析 实践目标 (1) 是监控你自己系统的运行状态,看有没有可疑的程序在运行. (2) 是分析一个恶意软件,就分析Exp2或Exp3中生成后门软件:分析工具尽量使用 ...
- What's new in XAML of .NET 4.0( .NET 4.0中XAML的新功能 )
原文 What's new in XAML of .NET 4.0 What's new in XAML of .NET 4.0 Easy Object References with {x:Refe ...
- [python]记录Windows下安装matplot的经历
最近学习在看<机器学习实战>一书,第二章的时候要用到Natplotlib画图,于是便开始安装Matplotlib.本文所用到的所有安装包都可以在文末的链接中找到. 首先从Matplotli ...