题目链接

题目大意:一共有Q(1<=Q<=50000)组操作,操作分为两种:

1.在x,y,z处添加一颗星星

2.询问以(x1,y1,z1)与(x2,y2,z2)为左上和右下顶点的矩形之间的星星数

所有坐标取值范围均为[1,1e9]

思路:由于坐标取值范围太大(即使离散化后也很大),3维的数组肯定开不下,所以只能另辟蹊径。

解法一(两重CDQ+树状数组,需将z坐标离散化):

1)将每个查询操作拆分为8个(容斥),将所有操作放入一个数组qr中

2)将所有操作按时间排序(其实不用,因为读入的顺序就是按时间排好的)

3)第一次分治:将qr中每个子区间按x坐标从小到大排序,将左区间元素与右区间查询放入qr2中

4)第二次分治(嵌套在第一次分治中):将qr2中每个子区间按y坐标从小到大排序,统计左区间元素对右区间查询的贡献(利用树状数组记录z值)

注意每次分治结束后,需将左右区间的所有元素按相应坐标大小归并排好序。另外离散化的时候注意下标要从1开始而不是从0开始,否则树状数组可能会陷入死循环(在这个地方T了n次...QAQ)

 #include<bits/stdc++.h>

 using namespace std;
const int N=5e5+;
struct QR {
int f,x,y,z,i;
} qr[N],qr2[N],qr3[N];
int c[N],n,ans[N],nq,tot,zz[N],maxz;
int lowbit(int x) {return x&-x;}
void add(int u,int x) {
for(; u<=maxz; u+=lowbit(u))c[u]+=x;
}
int get(int u) {
int ret=;
for(; u; u-=lowbit(u))ret+=c[u];
return ret;
} void cdq2(int l,int r) {
if(l==r)return;
int mid=(l+r)>>;
cdq2(l,mid),cdq2(mid+,r);
int L=l,R=mid+;
for(; R<=r; ++R)if(qr2[R].f) {
for(; L<=mid&&qr2[L].y<=qr2[R].y; ++L)if(!qr2[L].f)add(qr2[L].z,);
ans[qr2[R].i]+=get(qr2[R].z)*qr2[R].f;
}
for(int i=l; i<L; ++i)if(!qr2[i].f)add(qr2[i].z,-);
L=l,R=mid+;
for(int i=l; i<=r; ++i) {
if(R>r||(L<=mid&&qr2[L].y<=qr2[R].y))qr3[i]=qr2[L++];
else qr3[i]=qr2[R++];
}
for(int i=l; i<=r; ++i)qr2[i]=qr3[i];
} void cdq1(int l,int r) {
if(l==r)return;
int mid=(l+r)>>;
cdq1(l,mid),cdq1(mid+,r);
int L=l,R=mid+,m=;
for(; R<=r; ++R)if(qr[R].f) {
for(; L<=mid&&qr[L].x<=qr[R].x; ++L)if(!qr[L].f)qr2[m++]=qr[L];
qr2[m++]=qr[R];
}
if(m>)cdq2(,m-);
L=l,R=mid+;
for(int i=l; i<=r; ++i) {
if(R>r||(L<=mid&&qr[L].x<qr[R].x))qr2[i]=qr[L++];
else qr2[i]=qr[R++];
}
for(int i=l; i<=r; ++i)qr[i]=qr2[i];
} int main() {
int T;
scanf("%d",&T);
while(T--) {
nq=tot=;
memset(c,,sizeof c);
memset(ans,,sizeof ans);
scanf("%d",&n);
for(int i=; i<n; ++i) {
int f;
scanf("%d",&f);
if(f==) {
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
qr[nq++]= {,x,y,z,};
} else {
int x1,y1,z1,x2,y2,z2;
scanf("%d%d%d%d%d%d",&x1,&y1,&z1,&x2,&y2,&z2);
qr[nq++]= {,x2,y2,z2,tot};
qr[nq++]= {-,x1-,y2,z2,tot};
qr[nq++]= {-,x2,y1-,z2,tot};
qr[nq++]= {-,x2,y2,z1-,tot};
qr[nq++]= {,x1-,y1-,z2,tot};
qr[nq++]= {,x2,y1-,z1-,tot};
qr[nq++]= {,x1-,y2,z1-,tot};
qr[nq++]= {-,x1-,y1-,z1-,tot++};
}
}
maxz=;
for(int i=; i<nq; ++i)zz[maxz++]=qr[i].z;
sort(zz,zz+maxz);
maxz=unique(zz,zz+maxz)-zz;
for(int i=; i<nq; ++i)qr[i].z=lower_bound(zz,zz+maxz,qr[i].z)-zz+;
cdq1(,nq-);
for(int i=; i<tot; ++i)printf("%d\n",ans[i]);
}
return ;
}

解法二(三重CDQ,无需离散化):

1)2)3)同解法一,第四步将q2中每个子区间按z坐标从小到大排序,将左区间元素与右区间查询放入qr3中,然后利用类似归并排序求逆序对的方法对qr3中的贡献进行统计

 #include<bits/stdc++.h>

 using namespace std;
const int N=5e5+;
struct QR {
int f,x,y,z,i;
} qr[N],qr2[N],qr3[N],qr4[N];
int n,ans[N],nq,tot; void cdq3(int l,int r) {
if(l==r)return;
int mid=(l+r)>>;
cdq3(l,mid),cdq3(mid+,r);
int L=l,R=mid+,m=;
for(; R<=r; ++R)if(qr3[R].f) {
for(; L<=mid&&qr3[L].z<=qr3[R].z; ++L)if(!qr3[L].f)m++;
ans[qr3[R].i]+=m*qr3[R].f;
}
L=l,R=mid+;
for(int i=l; i<=r; ++i) {
if(R>r||(L<=mid&&qr3[L].z<=qr3[R].z))qr4[i]=qr3[L++];
else qr4[i]=qr3[R++];
}
for(int i=l; i<=r; ++i)qr3[i]=qr4[i];
} void cdq2(int l,int r) {
if(l==r)return;
int mid=(l+r)>>;
cdq2(l,mid),cdq2(mid+,r);
int L=l,R=mid+,m=;
for(; R<=r; ++R)if(qr2[R].f) {
for(; L<=mid&&qr2[L].y<=qr2[R].y; ++L)if(!qr2[L].f)qr3[m++]=qr2[L];
qr3[m++]=qr2[R];
}
if(m>)cdq3(,m-);
L=l,R=mid+;
for(int i=l; i<=r; ++i) {
if(R>r||(L<=mid&&qr2[L].y<=qr2[R].y))qr3[i]=qr2[L++];
else qr3[i]=qr2[R++];
}
for(int i=l; i<=r; ++i)qr2[i]=qr3[i];
} void cdq1(int l,int r) {
if(l==r)return;
int mid=(l+r)>>;
cdq1(l,mid),cdq1(mid+,r);
int L=l,R=mid+,m=;
for(; R<=r; ++R)if(qr[R].f) {
for(; L<=mid&&qr[L].x<=qr[R].x; ++L)if(!qr[L].f)qr2[m++]=qr[L];
qr2[m++]=qr[R];
}
if(m>)cdq2(,m-);
L=l,R=mid+;
for(int i=l; i<=r; ++i) {
if(R>r||(L<=mid&&qr[L].x<qr[R].x))qr2[i]=qr[L++];
else qr2[i]=qr[R++];
}
for(int i=l; i<=r; ++i)qr[i]=qr2[i];
} int main() {
int T;
scanf("%d",&T);
while(T--) {
nq=tot=;
memset(ans,,sizeof ans);
scanf("%d",&n);
for(int i=; i<n; ++i) {
int f;
scanf("%d",&f);
if(f==) {
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
qr[nq++]= {,x,y,z,};
} else {
int x1,y1,z1,x2,y2,z2;
scanf("%d%d%d%d%d%d",&x1,&y1,&z1,&x2,&y2,&z2);
qr[nq++]= {,x2,y2,z2,tot};
qr[nq++]= {-,x1-,y2,z2,tot};
qr[nq++]= {-,x2,y1-,z2,tot};
qr[nq++]= {-,x2,y2,z1-,tot};
qr[nq++]= {,x1-,y1-,z2,tot};
qr[nq++]= {,x2,y1-,z1-,tot};
qr[nq++]= {,x1-,y2,z1-,tot};
qr[nq++]= {-,x1-,y1-,z1-,tot++};
}
}
cdq1(,nq-);
for(int i=; i<tot; ++i)printf("%d\n",ans[i]);
}
return ;
}

两种解法复杂度均为O(nlog3n),但解法二比解法一常数大很多,这道题可以勉强A掉,而同样思路的BZOJ3262用同样的方法就会被卡掉。

HDU - 5126 stars (CDQ分治)的更多相关文章

  1. hdu 5126 stars cdq分治套cdq分治+树状数组

    题目链接 给n个操作, 第一种是在x, y, z这个点+1. 第二种询问(x1, y1, z1). (x2, y2, z2)之间的总值. 用一次cdq分治可以将三维变两维, 两次的话就变成一维了, 然 ...

  2. hdu 5830 FFT + cdq分治

    Shell Necklace Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)T ...

  3. hdu 5126 stars (四维偏序,离线,CDQ套CDQ套树状数组)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5126 思路:支持离线,那么我们可以用两次CDQ分治使四维降为二维,降成二维后排个序用树状数组维护下就好 ...

  4. hdu 4366 Successor - CDQ分治 - 线段树 - 树分块

    Sean owns a company and he is the BOSS.The other Staff has one Superior.every staff has a loyalty an ...

  5. Boring Class HDU - 5324 (CDQ分治)

    Mr. Zstu and Mr. Hdu are taking a boring class , Mr. Zstu comes up with a problem to kill time, Mr. ...

  6. HDU 5126 stars (四维偏序+树状数组)

    题目大意:略 题目传送门 四维偏序板子题 把插入操作和询问操作抽象成$(x,y,z,t)$这样的四元组 询问操作拆分成八个询问容斥 此外$x,y,z$可能很大,需要离散 直接处理四维偏序很困难,考虑降 ...

  7. HDU5126 stars(CDQ分治)

    传送门 大意: 向三维空间中加点,询问一个三维区间中点的个数. 解题思路: 带修改CDQ,将修改和询问一起插入CDQ分治询问. (询问可以由8个前缀和加减操作实现) 其中第一层CDQ维护x有序. 第二 ...

  8. HDU 5126 stars 4维偏序, CDQ套CDQ

    题目传送门 题意:在一个星空中,按着时间会出现一些点,现在john想知道,在某个时间内有多少个星星是的坐标是满足条件的.(x1<=x<=x2, y1 <= y <= y2, z ...

  9. hdu 1541 (cdq分治)

    Problem Description Astronomers often examine star maps where stars are represented by points on a p ...

随机推荐

  1. Nginx常用命令(加入系统服务)

    nginx 服务器重启命令,关闭 nginx -s reload :修改配置后重新加载生效 nginx -s reopen :重新打开日志文件 nginx -t -c /path/to/nginx.c ...

  2. Fidder详解之抓包

    前言 本文是博主发表的第一篇文章,如有傻逼之处,请大家见谅.最近遇到很多人说接口相关的问题,比如:什么是接口,我该怎么做接口测试,还有我总是抓不到APP上的https请求(这个巨坑,不知道坑了多少小白 ...

  3. Linux Shell基础 管道符和grep命令

    概述 管道符:管道符使用"丨"代表.如"命令1丨命令2".表示命令 1 的正确输出作为命令 2 的操作对象.命令 1 必须有正确输出,而命令 2 必须可以处理命 ...

  4. XML文件结构和基本语法

    XML文件的结构性内容,包括节点关系以及属性内容等等.元素是组成XML的最基本的单位,它由开始标记,属性和结束标记组成.就是一个元素的例子,每个元素必须有一个元素名,元素可以若干个属性以及属性值. x ...

  5. I.MX6Q(TQIMX6Q/TQE9)学习笔记——U-Boot移植

    其实Freescale的BSP移植文档已经将u-boot的移植步骤讲述的非常详细了,但为了以后方便查阅,还是按照自己的理解记录在这里. 获取源码 根据前一篇文章搭建好LTIB环境后就可以非常方便的导出 ...

  6. Squid 正向代理配置

    Squid 正向代理配置 1.删除主配置文件重写写入配置 rm -f /etc/squid/squid.conf 2.重新写入配置正向代理 vim /etc/squid/squid.conf # 监听 ...

  7. SOA 面向服务架构 阅读笔记(六)

    20 SOA质量 服务质量是成功的关键因素 20.1 了解SOA带来的无法预料的挑战 不同部门开发 每个开发的组件整合在一起,形成复合应用程序 整合业务流程,考虑质量问题 衡量SOA的质量. 事物质量 ...

  8. 主攻ASP.NET MVC4.0之重生:Jquery Mobile 面板

    左滑动面板效果: 右滑动面板效果: @{ ViewBag.Title = "JQuery Mobile Web Page"; } <!DOCTYPE html> < ...

  9. strspn() 和 strcspn() 函数【转】

    本文转载自:https://flyer103.wordpress.com/2011/06/03/strspn-%E5%92%8C-strcspn-%E5%87%BD%E6%95%B0/ 前几天在看一本 ...

  10. ubuntu ssh免密码登录

    目前很多服务(ceph,openstack等)都需要用到SSH使用ssh-key进行登录,而不能使用密码进行登录. 下面是配置步骤: 一.在SSH Client生成ssh key pair root@ ...