首先肯定是要膜拜CDQ大佬的。

题目背景

这是一道模板题

可以使用bitset,CDQ分治,K-DTree等方式解决。

题目描述

有 nn 个元素,第 ii 个元素有 a_iai​、b_ibi​、c_ici​ 三个属性,设 f(i)f(i) 表示满足 a_j \leq a_iaj​≤ai​ 且 b_j \leq b_ibj​≤bi​ 且 c_j \leq c_icj​≤ci​ 的 jj 的数量。

对于 d \in [0, n)d∈[0,n),求 f(i) = df(i)=d 的数量

输入输出格式

输入格式:

第一行两个整数 nn、kk,分别表示元素数量和最大属性值。

之后 nn 行,每行三个整数 a_iai​、b_ibi​、c_ici​,分别表示三个属性值。

输出格式:

输出 nn 行,第 d + 1d+1 行表示 f(i) = df(i)=d 的 ii 的数量。

输入输出样例

输入样例#1: 复制

10 3
3 3 3
2 3 3
2 3 1
3 1 1
3 1 2
1 3 1
1 1 2
1 2 2
1 3 2
1 2 1
输出样例#1: 复制

3
1
3
0
1
0
1
0
0
1

怎么看三维偏序呢?

其实就是一个三维的逆序对,没有这么高大上。

回想二维逆序对(普通逆序对)的求解方法:

1、树状数组

利用树状数组的前缀和查询性质,把原数组离散化成相对大小,然后从后往前查询,插入

2、归并排序

归并排序(这和CDQ分治很像,非常像,甚至可以说:归并排序就是cdq分治求二维偏序)

于是,回到正题,三维逆序对,哦不,是三维偏序。

第一维把它排序(在二维逆序对里,第一维是排好序的)

第二维把它塞到归并排序里,去求满足二维的个数,如果满足,塞到树状数组里

第三维用树状数组维护前缀和,就像求二维逆序对那样直接找出来个数。因为经过了前两层的筛选,这一层统计的个数就是最终的答案。

对于CDQ来说,其实最难得部分就是怎么合并两个区间。

说起来非常简单吧。。。但是作为一直规避归并排序的我来说,还是有小小的问题的。。

塞代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+;
struct node
{
int nth,a,b,c;
}a[maxn];
int n,k;
int f[maxn],same[maxn],t[maxn<<],ans[maxn];
inline int lowbit(int x)//树状数组
{
return x & - x ;
}
void add(int x,int y)
{
for(;x<=k;x+=lowbit(x))
{
t[x]+=y;
}
}
int ask(int x)
{
int res=;
for(;x;x-=lowbit(x))
{
res+=t[x];
}
return res;
}
bool cmp1(node a,node b)//对第一维进行排序
{
if(a.a!=b.a)return a.a<b.a;//第一关键字自然是第一个元素
if(a.b!=b.b)return a.b<b.b;//第二关键字尽量保证(题目要求大于等于)
else return a.c<b.c;
}
bool cmp2(node a,node b)
{
if(a.b!=b.b)return a.b<b.b;//归并时第二维进行排序
if(a.c!=b.c)return a.c<b.c;
else return a.a<b.a;
}
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,cmp2);//直接排序,下面计算答案贡献
for(int i=l;i<=r;i++)
{
if(a[i].a<=mid)//如果元素小于mid就说明符合二维的偏序
{
add(a[i].c,);//塞到树状数组里面
}
else
{
ans[a[i].nth]+=ask(a[i].c);//要不然就统计答案
}
}
for(int i=l;i<=r;i++)
{
if(a[i].a<=mid)
add(a[i].c,-);这里还要更新回去,给下一个分治用(注意,不能用memset,太大了,而且上面的if一定要加,可以省去不少个log的复杂度)
}
}
int main()
{
scanf("%d%d",&n,&k);
for(int i=;i<=n;i++)
{
scanf("%d%d%d",&a[i].a,&a[i].b,&a[i].c);
a[i].nth=i;//第一维
}
sort(a+,a+n+,cmp1);
for(int i=;i<=n;)
{
int j=i+;
while(j<=n&&a[i].a==a[j].a&&a[i].b==a[j].b&&a[i].c==a[j].c)
j++;
while(i<j)
same[a[i++].nth]=a[j-].nth;//去重
}
for(int i=;i<=n;i++)
{
a[i].a=i;
}
cdq(,n);
for(int i=;i<=n;i++)
f[ans[same[a[i].nth]]]++;
for(int i=;i<n;i++)
printf("%d\n",f[i]);
return ;
}

CDQ分治学习笔记(三维偏序题解)的更多相关文章

  1. 初学cdq分治学习笔记(可能有第二次的学习笔记)

    前言骚话 本人蒟蒻,一开始看到模板题就非常的懵逼,链接,学到后面就越来越清楚了. 吐槽,cdq,超短裙分治....(尴尬) 正片开始 思想 和普通的分治,还是分而治之,但是有一点不一样的是一般的分治在 ...

  2. CDQ分治学习笔记

    数据结构中的一块内容:$CDQ$分治算法. $CDQ$显然是一个人的名字,陈丹琪(NOI2008金牌女选手) 这种离线分治算法被算法界称为"cdq分治" 我们知道,一个动态的问题一 ...

  3. 三维偏序[cdq分治学习笔记]

    三维偏序 就是让第一维有序 然后归并+树状数组求两维 cdq+cdq不会 告辞 #include <bits/stdc++.h> // #define int long long #def ...

  4. CDQ分治 陌上花开(三维偏序)

    CDQ分治或树套树可以切掉 CDQ框架: 先分 计算左边对右边的贡献 再和 所以这个题可以一维排序,二维CDQ,三维树状数组统计 CDQ代码 # include <stdio.h> # i ...

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

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

  6. GIS案例学习笔记-三维生成和可视化表达

    GIS案例学习笔记-三维生成和可视化表达 联系方式:谢老师,135-4855-4328,xiexiaokui#qq.com 目的:针对栅格或者矢量数值型数据,进行三维可视化表达 操作时间:15分钟 案 ...

  7. CDQ分治学习思考

    先挂上个大佬讲解,sunyutian1998学长给我推荐的mlystdcall大佬的[教程]简易CDQ分治教程&学习笔记 还有个B站小姐姐讲解的概念https://www.bilibili.c ...

  8. BZOJ3262:陌上花开 & 洛谷3810:三维偏序——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=3262 https://www.luogu.org/problemnew/show/3810 Desc ...

  9. 『cdq分治和多维偏序问题』

    更新了三维偏序问题的拓展 cdq分治 \(cdq\)分治是一种由\(IOI\ Au\)选手\(cdq\)提出的离线分治算法,又称基于时间的分治算法. 二维偏序问题 这是\(cdq\)分治最早提出的时候 ...

随机推荐

  1. 从0开始学FreeRTOS-(列表&列表项)-6

    # FreeRTOS列表&列表项的源码解读 第一次看列表与列表项的时候,感觉很像是链表,虽然我自己的链表也不太会,但是就是感觉很像. 在FreeRTOS中,列表与列表项使用得非常多,是Free ...

  2. Tomcat7.0.40注册到服务启动报错error Code 1 +connector attribute sslcertificateFile must be defined when using ssl with apr

    Tomcat7.0.40 注册到服务启动遇到以下几个问题: 1.启动报错errorCode1 查看日志如下图: 解决办法: 这个是因为我的jdk版本问题,因为电脑是64位,安装的jdk是32位的所以会 ...

  3. 阿里云服务器ecs + tomcat + 域名解析 部署web页面

    1.购买ecs:https://www.aliyun.com/product/ecs?spm=5176.12825654.eofdhaal5.2.3bf92c4aYOB7gL&aly_as=A ...

  4. javascript生成规定范围的随机整数

    Math.Random()函数能够返回带正号的double值,该值大于等于0.0且小于1.0,即取值范围是[0.0,1.0)的左闭右开区间,返回值是一个伪随机选择的数,在该范围内(近似)均匀分布. 我 ...

  5. 安装VMworkstation和Centos虚拟机

    1.安装VMware workstation. 2.下一步. 3.可以选择安装位置,下面选项不选. 4.这两个选项不需要选. 5.下一步 6.安装 7. 8.点击许可证输入密钥,密钥在网上搜,然后就完 ...

  6. 基于 Web 端 3D 地铁站可视化系统

    前言 工业互联网,物联网,可视化等名词在我们现在信息化的大背景下已经是耳熟能详,日常生活的交通,出行,吃穿等可能都可以用信息化的方式来为我们表达,在传统的可视化监控领域,一般都是基于 Web SCAD ...

  7. Python之selenium+pytesseract 实现识别验证码自动化登录脚本

    今天写自己的爆破靶场WP时候,遇到有验证码的网站除了使用pkav的工具我们同样可以通过py强大的第三方库来实现识别验证码+后台登录爆破,这里做个笔记~~~ 0x01关于selenium seleniu ...

  8. Linux系统基础

    Linux系统基础 目录   简介 0x01 Linux文件与目录管理 0x02 Linux系统用户以及用户组管理 0x03文档的压缩与打包 0x04 apt安装软件 0x05 进程管理 标签 Lin ...

  9. [Luogu2458][SDOI2006]保安站岗

    题目描述 五一来临,某地下超市为了便于疏通和指挥密集的人员和车辆,以免造成超市内的混乱和拥挤,准备临时从外单位调用部分保安来维持交通秩序. 已知整个地下超市的所有通道呈一棵树的形状:某些通道之间可以互 ...

  10. std::wstring

    std::wstring主要用于 UTF-16编码的字符, std::string主要用于存储单字节的字符( ASCII字符集 ),但是也可以用来保存UTF-8编码的字符. UTF-8和UTF-16是 ...