题意: 简化就是有两种操作,一种是插入(x,y,z)这个坐标,第二种是查询(x1,y1,z1)到(x2,y2,z2)(x1<=x2,y1<=y2,z1<=z2)的长方体包含多少个点。

解析: 将查询分成8个点,离线做,离散化z值,
两次CDQ,第一次归并排x值,第二次归并排y值,z值用bit树维护更新
查询。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
using namespace std;
const int maxn=*;
int N,Q,ans[maxn];
struct node
{
int x,y,z,id,s;//(x,y,z)三维坐标,id编号,s代表状态
node(int x=,int y=,int z=,int id=,int s=)
:x(x),y(y),z(z),id(id),s(s){}
}A[maxn],B[maxn],C[maxn];//A保存原数组,B保存中间过程,C用于归并排序临时数组
bool cmpid(const node& a,const node& b){ return a.id<b.id; } //排id
bool cmpz(const node& a,const node& b){ return a.z<b.z; } //排z值
int tree[maxn];//bit树实现部分
int lowbit(int x){ return x&(-x); }
void Add(int i,int d){ for(;i<maxn;i+=lowbit(i)) tree[i]+=d; }
int Sum(int i)
{
int ret=;
for(;i>;i-=lowbit(i)) ret+=tree[i];
return ret;
}
void CDQ2(int l,int r) //归并排y值,对z值查询更新
{
if(l>=r) return;
int mid=(l+r)/;
CDQ2(l,mid);
CDQ2(mid+,r);
int ls=l,rs=mid+;
while(rs<=r)
{
while(ls<=mid&&B[ls].y<=B[rs].y) //选取y较小的
{
if(B[ls].s==) Add(B[ls].z,); //如果是0则需要插入bit树
ls++;
}
if(B[rs].s!=) ans[B[rs].id]+=Sum(B[rs].z)*B[rs].s; //右边的是查询
rs++;
}
while(ls>l) //恢复
{
ls--;
if(B[ls].s==) Add(B[ls].z,-);
}
ls=l,rs=mid+;
for(int i=l;i<=r;i++) //归并排序过程,排y值
{
if((ls<=mid&&B[ls].y<=B[rs].y)||rs>r) C[i]=B[ls++];
else C[i]=B[rs++];
}
for(int i=l;i<=r;i++) B[i]=C[i];
}
void CDQ1(int l,int r)//归并排x值,选取的过程是时序
{
if(l==r) return;
int mid=(l+r)/;
CDQ1(l,mid);
CDQ1(mid+,r);
int ls=l,rs=mid+,k=;
while(rs<=r)
{
while(ls<=mid&&A[ls].s!=) ls++; //前一半而且是查询不管
while(rs<=r&&A[rs].s==) rs++; //后一半而且是插入不管
if(rs>r) break; //这个地方可能难理解,仔细 想一下如果右边已经没有查询的操作了,
//剩下的左边的时序绝对比最后一次加到B中的查询的操作时序要大
if((A[ls].x<=A[rs].x&&ls<=mid)||rs>r) B[k++]=A[ls++];
else B[k++]=A[rs++];
}
if(k>) CDQ2(,k-); //再一次CDQ
ls=l,rs=mid+;
for(int i=l;i<=r;i++) //归并排序
{
if((ls<=mid&&A[ls].x<=A[rs].x)||rs>r) C[i]=A[ls++];
else C[i]=A[rs++];
}
for(int i=l;i<=r;i++) A[i]=C[i];
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
N=;
int type,x1,y1,z1,x2,y2,z2;
scanf("%d",&Q);
while(Q--)
{
scanf("%d",&type);
if(type==)
{
scanf("%d%d%d",&x1,&y1,&z1);
A[N++]=node(x1,y1,z1,N,); //要插入的点
}
else
{
scanf("%d%d%d",&x1,&y1,&z1);
scanf("%d%d%d",&x2,&y2,&z2);
A[N++]=node(x2,y2,z2,N,); //分成8个查询的点
A[N++]=node(x2,y1-,z2,N,-);
A[N++]=node(x1-,y2,z2,N,-);
A[N++]=node(x2,y2,z1-,N,-);
A[N++]=node(x1-,y1-,z2,N,);
A[N++]=node(x1-,y2,z1-,N,);
A[N++]=node(x2,y1-,z1-,N,);
A[N++]=node(x1-,y1-,z1-,N,-);
}
}
memset(ans,,sizeof(ans));
sort(A,A+N,cmpz); //按照z值排序
int ka=;
A[N].z=-;
for(int i=;i<N;i++)
if(A[i].z!=A[i+].z) A[i].z=ka++; //离散化
else A[i].z=ka;
sort(A,A+N,cmpid); //按照时序排回来
memset(tree,,sizeof(tree));
CDQ1(,N-);
sort(A,A+N,cmpid); //再排回来
for(int i=;i<N;i++) //输出答案
{
if(A[i].s==) continue;
int sum=;
for(int j=;j<;j++) sum+=ans[i+j];
printf("%d\n",sum);
i+=;
}
}
return ;
}

Hdu5126-stars(两次CDQ分治)的更多相关文章

  1. 胡扯两句——CDQ分治

    之前听大神讲过CDQ分治大概是个什么东西,但是一直还没有真正去搞过.今天稍微看了一下,写点自己的理解. 首先CDQ分治有两个条件. 条件1:可以分成两个独立互不影响的问题(这里的"独立&qu ...

  2. 【Luogu1393】动态逆序对(CDQ分治)

    [Luogu1393]动态逆序对(CDQ分治) 题面 题目描述 对于给定的一段正整数序列,我们定义它的逆序对的个数为序列中ai>aj且i < j的有序对(i,j)的个数.你需要计算出一个序 ...

  3. cdq分治的小结

    cdq分治 是一种特殊的分治 他的思想: 1.分治l,mid 2.分治mid+1,r 3.计算l,mid对mid+1,r的影响 3就是最关键的地方 这也是cdq的关键点 想到了这一步基本就可以做了 接 ...

  4. 【洛谷3157】[CQOI2011] 动态逆序对(CDQ分治)

    点此看题面 大致题意: 给你一个从\(1\)到\(n\)的排列,问你每次删去一个元素后剩余的逆序对个数. 关于\(80\)分的树套树 为了练树套树,我找到了这道题目. 但悲剧的是,我的 线段树套\(T ...

  5. luogu P3157 [CQOI2011]动态逆序对(CDQ分治)

    题目描述 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序 ...

  6. HDU5126 stars【CDQ分治】*

    HDU5126 stars Problem Description John loves to see the sky. A day has Q times. Each time John will ...

  7. HDU5126 stars(CDQ分治)

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

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

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

  9. HDU - 5126 stars (CDQ分治)

    题目链接 题目大意:一共有Q(1<=Q<=50000)组操作,操作分为两种: 1.在x,y,z处添加一颗星星 2.询问以(x1,y1,z1)与(x2,y2,z2)为左上和右下顶点的矩形之间 ...

随机推荐

  1. hdu2082:简单母函数

    题目大意: a,b,c,d...z这些字母的价值是1,2,3......26 给定 这26个字母分别的数量,求总价值不超过50的单词的数量 分析: 标准做法是构造母函数 把某个单词看作是,关于x的多项 ...

  2. FreeBSD简单配置SSH并用root远程登陆方法

    FreeBSD简单配置SSH并用root远程登陆方法 前言:最近下载了FreeBSD,在虚拟机上安装,第一步先要开启SSH服务,用终端putty软件可以实现在windows系统进行远程管理, 初级 = ...

  3. Android-67-Tomcat启动出错:Server Tomcat v7.0 Server at localhost failed to start.

     错误:Server Tomcat v7.0 Server at localhost failed to start.如图: 唉! ! !!图片上传不上去,悲哀啊!..仅仅能先写着错误提示语吧~~ ...

  4. [Javascript] Regex: '$`', '$&', '$''

    var input = "foobar"; var result = input.replace('bar', '$`'); // $`: replace 'bar' with e ...

  5. 寒哥细谈之AutoLayout全解

    文/南栀倾寒(简书作者)原文链接:http://www.jianshu.com/p/683fbcbfb705著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”. 看到群中好多朋友还停留在Fr ...

  6. openstack中glance组件images的全部python API 汇总

    感谢朋友支持本博客,欢迎共同探讨交流.因为能力和时间有限.错误之处在所难免,欢迎指正! 假设转载,请保留作者信息. 博客地址:http://blog.csdn.net/qq_21398167 原博文地 ...

  7. Unity 3D 动画帧事件

    前几天在项目开发中碰到一个这样的需求,RPG游戏中,特效和动画播放不同步的.假如主角在攻击NPC时,先实例化特效,后播放动画.动画毕竟是有一个时间长度的.等到动画播放攻击挥刀的那一瞬间时,特效可能早就 ...

  8. RMAN-configure命令

    在Oracle 10g中的配置情况 使用RMAN>show all; 可以显示出RMAN 配置参数为: CONFIGURE RETENTION POLICY TO REDUNDANCY 1; # ...

  9. 安装mysql时提示The host 'xxx' could not be looked up with resolveip的解决办法

    1.首先用cat查看/etc/hosts文件,会显示以下内容: 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.loca ...

  10. MySql 跟踪命令

    SHOW ; SHOW FULL PROCESSLIST; ; USE table1; ; SHOW PROFILES; ; SHOW TABLES; SHOW PROFILES; SHOW PROF ...