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)为左上和右下顶点的矩形之间 ...
随机推荐
- Flink状态专题:keyed state和Operator state
众所周知,flink是有状态的计算.所以学习flink不可不知状态. 正好最近公司有个需求,要用到flink的状态计算,需求是这样的,收集数据库新增的数据. ...
- 腾讯位置服务API快速入门
前言 之前项目有个需求,在网页上显示微信发送过来的位置信息,该开始想用百度地图,后来发现腾讯地图相对简单一点 快速入门 申请Key https://lbs.qq.com/guides/startup. ...
- C#文件下载流程
private bool DownloadPicture(string picUrl, string savePath, int timeOut) { bool ...
- 一份新的lilypond谱子,能设置页边距和设置换页符了
给学生做的一份乐谱,这回能设置页边距了,以及设置换页符了. 顺带能设置一些代码片段(snippet),可以用热键代替使用 设置页边距的snippet: \paper { %双引号里面填页面大小 #(s ...
- flask 异步celery使用
在开发过程中,耗时长,超时的任务经常发生,比如:获取后端某个大文件数据超时.需要后端计算任务超时,等等, 此时我们就会很自然的想到异步方式,根据需要完成的任务创建一个task_id, 由前端来监听该任 ...
- 【原创】POI操作Excel导入导出工具类ExcelUtil
关于本类线程安全性的解释: 多数工具方法不涉及共享变量问题,至于添加合并单元格方法addMergeArea,使用ThreadLocal变量存储合并数据,ThreadLocal内部借用Thread.Th ...
- 0x33 同余
目录 定义 同余类与剩余系 费马小定理 欧拉定理 证明: 欧拉定理的推论 证明: 应用: 定义 若整数 $a$ 和整数 $b$ 除以正整数 $m$ 的余数相等,则称 $a,b$ 模 $m$ 同余,记为 ...
- 多态、继承、this、super
先放一下多态的定义: (360词典上的哈) 多态(Polymorphism)按字面的意思就是"多种状态".在面向对象语言中,接口的多种不同的实现方式即为多态.引用Charlie C ...
- No!No!No! It's not fashion!
还记得搞怪的hold住姐Miss Lin么,对于人们常规的行为,Miss Lin会挑起夸张的眉毛说:"Oh my God, it's not fashion!".如果程序员圈子里有 ...
- Java——反射:运行时的类信息
RTTI的使用 如果不知道某个对象的确切类型,RTTI会告诉我们,但是有一个限制:这个类型在编译时必须已知,这样才能使用RTTI识别它,并利用这些信息做一些有用的事情. 2.什么情况下需要反射 假设 ...