cdq分治略解
前言
陌上花开,可缓缓归矣
——吴越王
- 寓意:意思是:田间阡陌上的花开了,你可以一边赏花,一边慢慢回来。
- 隐意:春天都到了,你怎么还没有回来。形容吴越王期盼夫人早日归来的急切心情。
Ask:那么这和cdq有什么关系呢?
Answer:并没有什么关系,增强语文水平而已,现在来看一到题目:陌上花开。这就有关系了吧。
题目大意是:有\(n\)个元素,第\(i\)个元素有\(a_i,b_i,c_i\)三个属性,设\(f(i)\)表示满足\(a_j≤a_i\)且\(b_j≤b_i\)且\(c_j≤c_i\)的\(j\)的数量。求\(f(i)=d\)的数量\(d\in[0,n)\)
做法1:暴力
\(O(n^2)\)的扫一遍求一下就好了。
#include<bits/stdc++.h>
int k,n,f[200001],a[200001],b[200001],c[200001],ans;
int main(){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
scanf("%d%d%d",&a[i],&b[i],&c[i]);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++)
if(a[j]<=a[i]&&b[j]<=b[i]&&c[j]<=c[i]&&i!=j)
ans++;
f[ans]++,ans=0;
}
for(int i=0;i<n;i++)
printf("%d\n",f[i]);
}
这个应该不需要多讲吧,普及组的难度,但不要说不需要,你在对拍的时候就需要他了
做法2: K-DTree
不会,我tcl
做法三:cdq分治
现在来正式讲一讲cdq分治
cdq分治
前置要求:
逆序对的问题是二维的,我们只需要讲一维排序,然后在用树状数组维护即可。
那么对于三维的陌上花开呢?我们还是可以用这个方法,首先先将数列按第一位排序,这样我们只需要考虑两维的情况。于是我们可以分治做了,将某一个序列\([l,r]\),分成段\([l,mid]\)和\([mid+1,r]\),然后在对\([l,r]\)这段区间的第二维进行排序。若点在排序前属于\([l,mid]\),树状数组单点修改;否则该点在排序前属于\([m+1,r]\),便统计一次。(其实就是类似于树状数组求逆序对的操作)
一定要记得去重,否则会出事的
code
#include<bits/stdc++.h>
using namespace std;
const int N=200001;
struct node{
int x,y,z,id;
}a[N];
int c[N<<2],k,n,b[N],bj[N],f[N];
int lowbit(int x){
return x&(-x);
}
int read(){
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9') f=(c=='-')?-1:1,c=getchar();
while(c>='0'&&c<='9') x=x*10+c-48,c=getchar();
return f*x;
}
void add(int x,int v){
while(x<=k)
c[x]+=v,x+=lowbit(x);
}
int sum(int x){
int ans=0;
while(x)
ans+=c[x],x-=lowbit(x);
return ans;
}
bool cmp1(const node & a , const 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 cmp2(const node & a , const node & b ){
if(a.y!=b.y)
return a.y<b.y;
if(a.z!=b.z)
return a.z<b.z;
return a.x<b.x;
}
void cdq(int l,int r){
if(l==r)
return ;
int mid=(l+r)>>1,flag;
cdq(l,mid),cdq(mid+1,r);
sort(a+l,a+r+1,cmp2);
for(int i=l;i<=r;i++)
(a[i].x<=mid)?add(a[i].z,1),flag=i:b[a[i].id]+=sum(a[i].z);
for(int i=l;i<=r;i++)
if(a[i].x<=mid)
add(a[i].z,-1);
}
int main(){
n=read(),k=read();
for(int i=1;i<=n;i++)
a[i].x=read(),a[i].y=read(),a[i].z=read(),a[i].id=i;
sort(a+1,a+1+n,cmp1);
for(int i=1;i<=n;){
int j=i+1;
while(j<=n&&a[j].x==a[i].x&&a[j].y==a[i].y&&a[j].z==a[i].z)
j++;
while(i<j)
bj[a[i].id]=a[j-1].id,i++;
}
for(int i=1;i<=n;i++)
a[i].x=i;
cdq(1,n);
for(int i=1;i<=n;i++)
f[b[bj[a[i].id]]]++;
for(int i=0;i<n;i++)
printf("%d\n",f[i]);
}
cdq分治略解的更多相关文章
- 偏序问题及CDQ分治详解
CDQ用来解决分治时左半部分对右半部分造成影响的问题. CDQ分治的经典问题是三维偏序问题. 要想解决三维偏序问题,首先你要知道什么是偏序.(废话) 一维偏序: 给出直线上的n个点,问有多少对点满足x ...
- 并不对劲的cdq分治解三维偏序
为了反驳隔壁很对劲的太刀流,并不对劲的片手流决定与之针锋相对,先一步发表cdq分治解三维偏序. 很对劲的太刀流在这里-> 参照一.二维偏序的方法,会发现一位偏序就是直接排序,可以看成通过排序使 ...
- 点分治&cdq分治 总结
游荡的孤高灵魂不需要羁绊之处. 洛谷题单 点分治 前置芝士 树的重心 树分治 例题略解 P3806 [模板]点分治1 板子题,先暴力找到整棵树的重心,然后先求出重心到各点的距离,进而算出他所在树的各个 ...
- ACdream 1157 Segments(CDQ分治)
题目链接:http://acdream.info/problem?pid=1157 Problem Description 由3钟类型操作:1)D L R(1 <= L <= R < ...
- HDU 5618 Jam's problem again CDQ分治 BC ROUND 70
题意:给你1e5个点(x,y,z),对于每一个点询问有多少个点(x1,y1,z1)满足x1<=x&&y1<=y&&z1<=z 分析:(官方题解奉上)很 ...
- $CDQ$分治总结
A.\(CDQ\) 分治 特别基础的教程略. \(CDQ\)分治的优缺点: ( 1 )优点:代码量少,常数极小,可以降低处理维数. ( 2 )缺点:必须离线处理. \(CDQ\)分治与其他分治最本质的 ...
- Codeforces 848C Goodbye Souvenir [CDQ分治,二维数点]
洛谷 Codeforces 这题我写了四种做法-- 思路 不管做法怎样,思路都是一样的. 好吧,其实不一样,有细微的差别. 第一种 考虑位置\(x\)对区间\([l,r]\)有\(\pm x\)的贡献 ...
- 【BZOJ2001】[HNOI2010]城市建设(CDQ分治,线段树分治)
[BZOJ2001][HNOI2010]城市建设(CDQ分治,线段树分治) 题面 BZOJ 洛谷 题解 好神仙啊这题.原来想做一直不会做(然而YCB神仙早就切了),今天来怒写一发. 很明显这个玩意换种 ...
- bzoj1492/luogu4027 货币兑换 (斜率优化+cdq分治)
设f[i]是第i天能获得的最大钱数,那么 f[i]=max{在第j天用f[j]的钱买,然后在第i天卖得到的钱,f[i-1]} 然后解一解方程什么的,设$x[j]=\frac{F[j]}{A[j]*Ra ...
随机推荐
- PHP面向对象深入研究之【高级特性】
静态属性 <?php class StaticExample { static public $aNum = 0; // 静态共有属性 static public function sayHel ...
- 小记一次mysql启动失败没有日志的处理
本来mysql好的,之前清理了一次tmp下的东西,mysql在查询的时候提示: Can't create/write to file '/tmp/ib0n3frL 然后停止启动: [root@sevc ...
- php写一个判断是否有cookie的脚本
前言: 刚刚学习完cookie函数,写个练习. 0x01: //其实第二个应该改为elseif,但是我懒.啊哈 <?php $vlas="BnJhiFoPS4"; if(is ...
- python学习——练习题(4)
""" 题目:输入某年某月某日,判断这一天是这一年的第几天? """ import datetime import time from fu ...
- Android 4.4 外置卡
虾米.酷狗.百度地图.UC浏览器 下载 可以设置下载路径保存到外置SD卡上. 其他的软件目前还不支持. 最终Android 4.2是可以选择的,后来Android禁用了外置卡,以上软件是如何实现的?
- JAVA的对称加密算法AES——加密和解密
出自: http://blog.csdn.net/hongtashan11/article/details/6599645 http://www.cnblogs.com/liunanjava/p/42 ...
- Oracle行转列LISTAGG函数
工作过程中需要将查询的数据分组并显示在一行.以往的工作经验,在sql server中可以用for xml path来实现. 现提供Oracle数据库的行转列方式 oracle11g官方文档简介如下: ...
- 【291】Python 中字符串添加到剪贴板
参考:如何使用Python将字符串复制到Windows上的剪贴板上? 实现代码如下: from Tkinter import Tk r = Tk() r.withdraw() r.clipboard_ ...
- request.getHeader("x-forwarded-for")这是什么意思
request.getHeader,简单的说就是获取请求的头部信息,根据http协议,它能获取到用户访问链接的信息,以下是我们常用的: request.getHeader("referer& ...
- 01 java断言assert初步使用:断言开启、断言使用
参考文件:http://blog.sina.com.cn/s/blog_59c9412d0100fd55.html 1 说明 java断言assert是jdk1.4引入的. jvm断言默认是关闭的. ...