HDU 5126 stars 4维偏序, CDQ套CDQ
题意:在一个星空中,按着时间会出现一些点,现在john想知道,在某个时间内有多少个星星是的坐标是满足条件的。(x1<=x<=x2, y1 <= y <= y2, z1 <= z <= z2).
题解:先简化问题,如果我们就统计出现所有 x <= x2 , y <= y2, z <= z2的点的话,这就是一个4维偏序题。
对于这个统计点数来说, 我们先按照题目给定点的顺序来进行CDQ, 这样在CDQ内只有左边的添加点会对右边的询问点产生影响,然后我们再把这些会对答案找出影响的点拿出来,
对这些点进行关于X轴内一个sort,对于sort完的结果,我们再进行cdq, 这样在cdq内还是只有左边的左边的添加点会对右边的询问点产生影响,然后我们再把这些会对答案找出影响的点拿出来。
这样就变成了2维偏序题了, 再对y sort, 然后for一遍询问答案把答案加进去就好了。
现在的问题就变成了怎么询问这个长方体内点的个数。 我们可以用差分的思想去维护这个矩形。
我们对一次询问可以拆成8次询问。
Q1( X1-1, Y1-1, Z2) Q2 (X1-1, Y2, Z2) Q3 (X2, Y1-1, Z2) Q4(X2,Y2,Z2)
Q5( X1-1, Y1-1, Z1-1) Q6 (X1-1, Y2, Z1-1) Q7 (X2, Y1-1, Z1-1) Q8(X2,Y2,Z1-1)
可以发现 Q1-Q2-Q3+Q4 得到的是 z <= z2 x1<=x <= x2 && y1 <= y <= y2 的点的个数和。
现在我们在减去 z <= z1-1 x1<=x <= x2 && y1 <= y <= y2 的个数和就是答案了。
在CDQ的过程中, 我们可以加上一个剪枝 即对于这个CDQ来说,如果左边没有添加点 或者 右边没有询问点 就再进行处理了, 因为不会对答案造成影响。
代码:
#include<bits/stdc++.h>
using namespace std;
#define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
#define LL long long
#define ULL unsigned LL
#define fi first
#define se second
#define pb push_back
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lch(x) tr[x].son[0]
#define rch(x) tr[x].son[1]
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
typedef pair<int,int> pll;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const LL mod = (int)1e9+;
const int N = 1e6 + ;
struct Node{
int x, y, z, op, id;
}A[N], B[N], C[N];
int ans[N];
int zz[N];
int tot = ;
int zsz;
int bit[N];
void add(int x, int v){
while(x <= zsz){
bit[x] += v;
x += x & (-x);
}
}
int query(int x){
int ret = ;
while(x > ){
ret += bit[x];
x -= x & (-x);
}
return ret;
}
bool cmp_x(Node & n1, Node & n2){
if(n1.x != n2.x) return n1.x < n2.x;
if(n1.y != n2.y) return n1.y < n2.y;
if(n1.z != n2.z) return n1.z < n2.z;
return n1.id < n2.id;
}
bool cmp_y(Node & n1, Node & n2){
if(n1.y != n2.y) return n1.y < n2.y;
if(n1.z != n2.z) return n1.z < n2.z;
return n1.id < n2.id;
}
void cdq(int l, int r){
if(l >= r) return ;
int m = l+r >> ;
cdq(l, m); cdq(m+, r);
int k = ;
for(int i = l; i <= m; i++)
if(!B[i].id) C[++k] = B[i];
for(int i = m+; i <= r; i++)
if(B[i].id) C[++k] = B[i];
if(C[].id != || C[k].id == ) return ;/// 剪枝
sort(C+, C++k, cmp_y);
for(int i = ; i <= k; i++){
if(C[i].op)
ans[C[i].id] += query(C[i].z) * C[i].op;
else
add(C[i].z, );
}
for(int i = ; i <= k; i++){
if(C[i].op);
else add(C[i].z, -);
}
}
void CDQ(int l, int r){
if(l == r) return ;
int m = l+r >> ;
CDQ(l,m); CDQ(m+,r);
int k = ;
for(int i = l; i <= m; i++)
if(!A[i].id) B[++k] = A[i];
for(int i = m+; i <= r; i++)
if(A[i].id) B[++k] = A[i];
if(B[].id != || B[k].id == ) return ;/// 剪枝
sort(B+, B++k, cmp_x);
cdq(,k);
} inline void nownode(int x, int y, int z, int op, int id){
++tot; A[tot].x = x; A[tot].y = y; zz[tot] = z;
A[tot].z = z; A[tot].op = op; A[tot].id = id;
}
int main(){
int T;
scanf("%d", &T);
while(T--){
int n, op, x1, y1, z1, x2, y2, z2, m = ;
tot = ;
scanf("%d", &n);
for(int i = ; i <= n; i++){
scanf("%d", &op);
if(op == ){
scanf("%d%d%d", &x1, &y1, &z1);
nownode(x1, y1, z1, , );
}
else {
m++;
ans[m] = ;
scanf("%d%d%d", &x1, &y1, &z1);
scanf("%d%d%d", &x2, &y2, &z2);
nownode(x2,y2,z2,,m);
nownode(x1-,y1-,z2,,m);
nownode(x2,y1-,z2,-,m);
nownode(x1-,y2,z2,-,m); nownode(x2,y2,z1-,-,m);
nownode(x1-,y1-,z1-,-,m);
nownode(x2,y1-,z1-,,m);
nownode(x1-,y2,z1-,,m);
}
}
sort(zz+, zz+tot+);
zsz = unique(zz+, zz+tot+) - zz - ;
for(int i = ; i <= tot; i++)
A[i].z = lower_bound(zz+, zz++zsz, A[i].z) - zz;
CDQ(, tot);
for(int i = ; i <= m; i++)
printf("%d\n", ans[i]);
}
return ;
}
HDU 5126 stars 4维偏序, CDQ套CDQ的更多相关文章
- HDU - 5126: stars (求立方体内点数 CDQ套CDQ)
题意:现在给定空空的三维平面,有加点操作和询问立方体点数. 思路:考虑CDQ套CDQ.复杂度是O(NlogN*logN*logN),可以过此题. 具体的,这是一个四维偏序问题,4维分别是(times, ...
- cogs2479 偏序(CDQ套CDQ)
题目链接 思路 四维偏序 \(CDQ\)套\(CDQ\),第一维默认有序.第二维用第一个\(CDQ\)变成有序的.并且对每个点标记上第一维属于左边还是右边.第二个\(CDQ\)处理第三维,注意两个\( ...
- [HZOI 2016] 偏序(CDQ套CDQ)
传送门 思路: 就是cdq套cdq的模板题 #include <bits/stdc++.h> using namespace std; typedef long long ll; cons ...
- HDU5126---stars (CDQ套CDQ套 树状数组)
题意:Q次操作,三维空间内 每个星星对应一个坐标,查询以(x1,y1,z1) (x2,y2,z2)为左下顶点 .右上顶点的立方体内的星星的个数. 注意Q的范围为50000,显然离散化之后用三维BIT会 ...
- 【教程】CDQ套CDQ——四维偏序问题
前言 上一篇文章已经介绍了简单的CDQ分治,包括经典的二维偏序和三维偏序问题,还有带修改和查询的二维/三维偏序问题.本文讲介绍多重CDQ分治的嵌套,即多维偏序问题. 四维偏序问题 给定N( ...
- 四维偏序 CDQ套CDQ
对CDQ深一步的理解 昨天做了一道CDQ,看了一堆CDQ可做的题,今天又做了一道四维偏序 感觉对CDQ的理解又深了一点,故来写一写现在自己对于CDQ的理解 CDQ其实就是实现了这样的一个问题的转化: ...
- hdu 5126 stars (四维偏序,离线,CDQ套CDQ套树状数组)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5126 思路:支持离线,那么我们可以用两次CDQ分治使四维降为二维,降成二维后排个序用树状数组维护下就好 ...
- hdu 5126 stars cdq分治套cdq分治+树状数组
题目链接 给n个操作, 第一种是在x, y, z这个点+1. 第二种询问(x1, y1, z1). (x2, y2, z2)之间的总值. 用一次cdq分治可以将三维变两维, 两次的话就变成一维了, 然 ...
- HDU - 5126 stars (CDQ分治)
题目链接 题目大意:一共有Q(1<=Q<=50000)组操作,操作分为两种: 1.在x,y,z处添加一颗星星 2.询问以(x1,y1,z1)与(x2,y2,z2)为左上和右下顶点的矩形之间 ...
随机推荐
- Java基础之十五 泛型
第十五章 泛型 一般的类和方法,只能使用具体的类型:要么是基本类型,要么是自定义类型.如果要编写可以应用于多种类型的代码,这种刻板的限制对代码的束缚就会很大. 在面对对象编程语言中,多态算是一种泛化机 ...
- c# 控制台console进度条
1 说明 笔者大多数的开发在 Linux 下,多处用到进度条的场景,但又无需用到图形化界面,所以就想着弄个 console 下的进度条显示. 2 步骤 清行显示 //清行处理操作 int curren ...
- java中对事务的理解
一.什么是事务 事务是访问数据库的一个操作序列,数据库应用系统通过事务集来完成对数据库的存取. 二.事务的原则(ACID) 原子性:事务要么全部都被执行,要么就全都不被执行,如果有子事务提交失败,那么 ...
- DesignPattern系列__06迪米特原则
迪米特原则定义 迪米特原则,也叫最少知道原则,即一个类应该对自己依赖的类知道的越少越好,而你被依赖的类多么复杂,对我都没有关系.也就是说,对于别依赖的类来说,不管业务逻辑多么复杂,都应该尽量封装在类的 ...
- 携程 Apollo 配置中心传统 .NET 项目集成实践
官方文档存在的问题 可能由于 Apollo 配置中心的客户端源码一直处于更新中,导致其相关文档有些跟不上节奏,部分文档写的不规范,很容易给做对接的新手朋友造成误导. 比如,我在参考如下两个文档使用传统 ...
- CodeGlance右侧窗口缩略图消失不见
说明下问题,idea中的CodeGlance插件会在右侧显示缩略图,可以快速定位代码.今天遇到个问题升级了插件后右侧窗口消失.经过卸载插件,重启,reset一系列操作后还是没能恢复. 能去搜索引擎搜索 ...
- hdu1241 油田计数
具体思路:求联通块,在"@“的周围进行dfs,使用8个方向向量来代表搜索的方向 贴一下我的主要代码段: int dir[8][2]={{1,1},{-1,-1},{1,-1},{-1,1}, ...
- 在MAC终端下打开Finder:
在Terminal中打开Finder: open . 在Finder中打开Terminal: 系统偏好设置 -> 键盘 -> 快捷键 -> 服务,勾选「新建位于文件夹位置的终端窗口」
- [原创实践]redhat linux 5.3搭建Nexus
1:下载安装JDK,配置好环境变量(JAVA_HOME等) 下载linux下64位的jdk-7u45-linux-x64.tar.gz(百度网盘下载,官网的jdk-7u51-linux-x64.tar ...
- 28岁,转行学 IT 靠谱吗?
前几天在知乎上,刷到这么一个问题 鉴于有不少人看了我的blog给我私信一些职业规划相关的问题,讨论很多的就是担心自己年龄是否还适合转行. 于是决定静心下来码了一篇回答, 同时搬到博客园来供大家消遣.. ...