陌上花开——CDQ分治
传送门
“CDQ分治”从来都没有听说过,写了这题才知道还有这么神奇的算法。
(被逼无奈)。w(゚Д゚)w
于是看了不少dalao的博客,对CDQ算法粗浅地了解了一点。(想要了解CDQ的概念,可以看下这位dalao的博客)
所以,这道题要怎么做呢。。。
根据,CDQ分治理论,这题按照题意建出来储存信息的数组很明显是个三维的。很巧的是,CDQ分治的好处之一就是降维(根据官方民间说法,每降一维要付出一个log的时间代价)。则本题的三维数组,根据CDQ就有:第一维用来直接排序,第二维做CDQ分治,第三维做树状数组。
为了能够更加透彻地理解此题思路,借鉴了洛谷dalao的题解。
【解题思路】
- 这题有很多解法碰巧我们是作为CDQ分治的例题,于是这里就只介绍CDQ分治的解法
- 一道三维偏序,所以先把所有属性进行多关键字排序,先按a排序,再按b排序,最后按c排序,这就保证了在数列里面,后面的a会比前面的a要大(相当于把a离散化)。
- 接着就进行CDQ分治,对于一个区间l到r来说,a是已经排好序的。在CDQ分治完l--mid和mid+1--r这两个区间后,把l到r进行多关键字排序,这次先按b排序,再按c排序,最后按a排序,这就再保证了b的要求。
- 然后像CDQ分治需要的那样,把小于等于mid的a的贡献统计起来,把1-c的区间全部加1,优化大于mid的值的答案。这是一个区间修改,单点查询的操作,可以用线段树或者树状数组解决,本人为了方便用了树状数组。
- 记得最后还原树状数组。注意,如果直接对整个数组进行memset有可能会超时,我们只需对直接的操作进行反操作,把小于等于mid的a中,1-c的区间全部加-1即可。
- 最后进行判重(为什么要判重呢?因为如果有几个相同的量,我们CDQ分治的时候并没有管它,直接计算就会把所有结果都计算出来。这是你如果不判重,那么就会把一个答案反复累加,最终答案就会变大)
——摘自洛谷题解
那么融合了各位dalao的CDQ精华,以及本蒟蒻对CDQ的理解(+注释)后,就有了AC的极简代码。
- #include<algorithm>
- #include<cstdio>
- using namespace std;
- #define maxn 100005
- struct node{int x,y,z,num,ans;}a[maxn];
- int n,m,tot,ans[maxn],sum[maxn<<];
- inline bool cmp2(const node&a,const node&b)
- {
- if(a.y!=b.y) return a.y<b.y;
- return a.z<b.z;
- }
- inline bool cmp1(const node&a,const node&b)
- {
- if(a.x!=b.x) return a.x<b.x;
- return cmp2(a,b);
- }
- inline void Add(int x,int y)//极简的树状数组
- {
- for(;x<=m;x+=x&(-x)) sum[x]+=y;
- }
- inline int Quary(int x)//合并左右子区间的贡献
- {
- int ans=;
- for(;x;x-=x&(-x)) ans+=sum[x];
- return ans;
- }
- inline void CDQ(int l,int r)
- {
- if(l==r) return;
- int mid=l+r>>;
- CDQ(l,mid);CDQ(mid+,r);//先递归处理子问题
- sort(a+l,a+mid+,cmp2);
- sort(a+mid+,a+r+,cmp2);//把两个子问题的第一维分别进行排序。
- for(int i=mid+,j=l;i<=r;i++)
- {
- while(j<=mid&&a[j].y<=a[i].y) //若第二维的左子区间的a[j].y对右子区间产生了贡献
- Add(a[j].z,a[j].num),j++;//就把第三维的a[j].z扔进树状数组
- a[i].ans+=Quary(a[i].z);//归并排序
- }
- for(int i=l,max=a[r].y;i<=mid&&a[i].y<=max;i++) Add(a[i].z,-a[i].num);//清空树状数组(作案不留痕迹)
- }
- int main()
- {
- scanf("%d%d",&n,&m);
- for(int i=;i<=n;i++)
- scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
- sort(a+,a+n+,cmp1);//按第一维排序
- for(int i=;i<=n;i++,a[tot].num++)
- if(a[i].x!=a[tot].x||a[i].y!=a[tot].y||a[i].z!=a[tot].z)
- a[++tot]=a[i];//把可以符合题意的x,y,z先找出来,同时统计个数(分别)(相当于去重)
- CDQ(,tot);//进行CDQ分治
- for(int i=;i<=tot;i++)
- ans[a[i].ans+a[i].num-]+=a[i].num;//把重复的加回来
- for(int i=;i<n;i++)
- printf("%d\n",ans[i]);
- return ;
- }
陌上花开——CDQ分治的更多相关文章
- P3810 陌上花开 CDQ分治
陌上花开 CDQ分治 传送门:https://www.luogu.org/problemnew/show/P3810 题意: \[ 有n 个元素,第 i 个元素有 a_i. b_i. c_i 三个属性 ...
- 【BZOJ-3262】陌上花开 CDQ分治(3维偏序)
3262: 陌上花开 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 1439 Solved: 648[Submit][Status][Discuss ...
- bzoj3262陌上花开 cdq分治
3262: 陌上花开 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 2794 Solved: 1250[Submit][Status][Discus ...
- 洛谷P3810 陌上花开 CDQ分治(三维偏序)
好,这是一道三维偏序的模板题 当然没那么简单..... 首先谴责洛谷一下:可怜的陌上花开的题面被无情的消灭了: 这么好听的名字#(滑稽) 那么我们看了题面后就发现:这就是一个三维偏序.只不过ans不加 ...
- 【CJOJ2433】陌上花开 CDQ分治
[CJOJ2433]陌上花开 CDQ呲嘚秋分治 WA果然呲嘚秋分治跑得比树套树还快!!!(md理论复杂度不是一样的吗) 但树套树不知道比呲嘚秋高到哪里去辣装X用 Orz hzwer 第一维sort,第 ...
- 【BZOJ3262】陌上花开 cdq分治
[BZOJ3262]陌上花开 Description 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量.定义 ...
- bzoj3262: 陌上花开(cdq分治+树状数组)
3262: 陌上花开 题目:传送门 题解: %%%cdq分治 很强大的一个暴力...感觉比分块高级多了 这道题目就是一个十分经典的三维偏序的例题: 一维直接暴力排序x 二维用csq维护y 三维用树状数 ...
- BZOJ 3262: 陌上花开 [CDQ分治 三维偏序]
Description 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量.定义一朵花A比另一朵花B要美丽,当 ...
- bzoj 3262 陌上花开 - CDQ分治 - 树状数组
Description 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量.定义一朵花A比另一朵花B要美丽,当 ...
随机推荐
- [转载]谈谈document.ready和window.onload的区别
在Jquery里面,我们可以看到两种写法:$(function(){}) 和$(document).ready(function(){}) 这两个方法的效果都是一样的,都是在dom文档树加载完之后执行 ...
- Lambda表达式select()和where()的区别
可能很多同学和我一样对于select()和where()区别并不是太清晰,其实两者还是有本质区别的. 1.where()用法:必须加条件,且返回对象结果. static void Main(strin ...
- jquery操作节点
var v= $("input[type='checkbox'][name='ids']:checked").closest('tr').find('td:eq(2)').map( ...
- 前端框架VUE----webpack打包工具的使用
在这里我仅仅的是对webpack做个讲解,webpack这个工具非常强大,解决了我们前端很繁琐的一些工具流程繁琐的事情.如果感兴趣的同学,还是看官网吧. 中文链接地址:https://www.webp ...
- 怎样从外网访问内网MySQL数据库?
本地安装了一个MySQL数据库,只能在局域网内访问到,怎样从外网也能访问到本地的MySQL数据库呢?本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动MySQL数据库 默认安装的MySQL ...
- 虚拟继承C++
C++中虚拟继承的概念 为了解决从不同途径继承来的同名的数据成员在内存中有不同的拷贝造成数据不一致问题,将共同基类设置为虚基类.这时从不同的路径继承过来的同名数据成员在内存中就只有一个拷贝,同一个函数 ...
- 详解Django中六个常用的自定义装饰器
装饰器作用 decorator是当今最流行的设计模式之一,很多使用它的人并不知道它是一种设计模式.这种模式有什么特别之处? 有兴趣可以看看Python Wiki上例子,使用它可以很方便地修改对象行为, ...
- 微信小程序canvas把正方形图片绘制成圆形
wxml代码: <view class="result-page"> <canvas canvas-id='firstCanvas' style='width:1 ...
- TCP编程:系统出现 TIME_WAIT 原因及解决办法
解决办法 打开 sysctl.conf 文件,修改以下几个参数: net.ipv4.tcp_tw_recycle = 1net.ipv4.tcp_tw_reuse = 1net.ipv4.tcp_ti ...
- Java 之 FileReader FileInputStream InputStreamReader BufferedReader 作用与区别
ava.io下面有两个抽象类:InputStream和ReaderInputStream是表示字节输入流的所有类的超类Reader是用于读取字符流的抽象类InputStream提供的是字节流的读取,而 ...