这题说的是给了三维空间然后操作 寻求在 x1,y1,z1    x2, y2, z2; (x1<x2, y1<y2,z1<z2) 计算出在 以这两个端点为右下和左上端点的方体内的点的个数。CDQ 分治第一次听说,

在一个方体内使用容斥原理,然后不断的将剩下的点分成两个部分,然后这样不断地下去,对于每个部分在进行一次CDQ然后,再使用BIT求解,这样我们可以看看他这神奇的CDQ,他先是这样的,第一次CDQ先对在区间内的点进行x轴排序,排完后然后将这些点按照y轴进行合并,这样做的好处是想想二分后的一部分在一侧另一部分只会用到前一部分的,用这种方法可以让后面的所有的点都得到他被包含的查询内、

cdq套cdq套bit

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string.h>
using namespace std;
const int maxn=50005;
struct point{
int x,y,z,delt,qnum,kind;
point(){}
point(int a,int b, int c,int d,int e,int f){
this->x=a;this->y=b;this->z=c;this->delt=d;
this->qnum=e; this->kind=f;
}
}star[maxn*8],start3[maxn*8];
int Z[maxn*8],tot,qnum,ans[maxn*8],N,C[maxn*8];
bool use[maxn*8];
int lowbit(int x){ return x&(-x); }
void aDD(int loc, int val){
while(loc<=N){
C[loc]+=val;
loc+=lowbit(loc);
}
}
int sum(int loc){
int s=0;
while(loc>0){
s+=C[loc];
loc-=lowbit(loc);
}
return s;
}
void add(int x,int y,int z,int delt,int qnum,int kind ){
star[tot]=point(x,y,z,delt,qnum,kind);
Z[tot]=z;++tot;
}
void scatter(){
sort(Z,Z+tot);
N=unique(Z,Z+tot)-Z;
for(int i=0; i<tot; ++i)
star[i].z=lower_bound(Z,Z+N,star[i].z)-Z+1;
}
bool cmp1(point A, point B){
return A.x<B.x||(A.x==B.x&&A.qnum<B.qnum);
}
bool cmp2(point A, point B){
return A.y<B.y||(A.y==B.y&&A.qnum<B.qnum);
}
void CDQ2(int L, int R){
if(L>=R) return ;
int mid=(R+L)>>1;
CDQ2(L,mid);
CDQ2(mid+1,R);
int j=L;
for(int i=mid+1;i<=R; ++i){ for( ;j<=mid && ( start3[j].y <= start3[i].y ) ; ++j )
if(start3[j].kind==0){
aDD(start3[j].z,start3[j].delt);
}
ans[start3[i].qnum]+=sum(start3[i].z)*start3[i].delt;
}
for(int i=L; i<j; ++i)
if(start3[i].kind==0)
aDD(start3[i].z,-start3[i].delt);
inplace_merge(start3+L,start3+mid+1,start3+R+1,cmp2);
}
void CDQ1(int L, int R){
if(L>=R) return ;
int mid =(L+R)>>1;
CDQ1(L, mid );
CDQ1(mid+1,R);
int num=0;
for(int i=L; i<=mid; ++i)
if(star[i].kind==0)
start3[num++]=star[i];
for(int i=mid+1;i<=R; ++i)
if(star[i].kind==1)
start3[num++]=star[i];
sort(start3,start3+num,cmp1);
CDQ2(0,num-1);
}
int main()
{
int cas;
scanf("%d",&cas);
memset(use,false,sizeof(use));
memset(ans,0,sizeof(ans));
while(cas--){
int Q ;
tot=qnum=0;
scanf("%d",&Q);
for(int i=0; i<Q; ++i){
int A;
scanf("%d",&A);
if(A==1){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add( x, y, z, 1, qnum, 0);qnum++;
}else{
int x1,y1,z1,x2,y2,z2;
use[qnum]=true;
scanf("%d%d%d%d%d%d",&x1,&y1,&z1,&x2,&y2,&z2);
add(x1-1,y1-1,z1-1,-1,qnum,1);
add(x1-1,y1-1,z2 , 1,qnum,1);
add(x1-1,y2 ,z1-1, 1,qnum,1);
add(x1-1,y2 ,z2 ,-1,qnum,1);
add(x2 ,y2 ,z1-1,-1,qnum,1);
add(x2 ,y2 ,z2 , 1,qnum,1);
add(x2 ,y1-1,z1-1, 1,qnum,1);
add(x2 ,y1-1, z2,-1,qnum,1);
qnum++;
} }
scatter();
CDQ1(0,tot-1);
for(int i=0; i<qnum; ++i){ if(use[i]==true) printf("%d\n",ans[i]);
use[i]=false; ans[i]=0;
}
} return 0;
}

这里有一个方法使用cdq里面套了一个BIT 然后套 了一个Treap 使用cdq分治,然后离散了x 然后在BiT上放上棵Treap,通过Treap 去找到对应的个数

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string.h>
#include <cstdlib>
using namespace std;
const int maxn=+;
struct Node{
Node *ch[];
int r;
int y;
int spoint;
int loc;
void maintain(){
spoint=loc;
if(ch[]!=NULL) spoint+=ch[]->spoint;
if(ch[]!=NULL) spoint+=ch[]->spoint;
}
Node(int v):y(v){ r=rand(); spoint=; loc=; ch[]=ch[]=NULL; }
int cmp(int x){
if(x==y) return -;
return x<y?:;
}
};
Node *T[maxn*];
int now[maxn*],Time;
void removetree(Node *&o){
if(o->ch[]!=NULL) removetree(o->ch[]);
if(o->ch[]!=NULL) removetree(o->ch[]);
delete o;
o=NULL;
}
void rotate(Node *&o, int d){
Node *k=o->ch[d^]; o->ch[d^]=k->ch[d]; k->ch[d]=o;
o->maintain(); k->maintain(); o=k;
}
void insert(Node *&o, int y){
if(o==NULL){
o=new Node(y);
}else{
int d=o->cmp(y);
if(d==-){
o->loc++;
}else{
insert(o->ch[d],y);
if( o->ch[d]->r > o->r ) rotate(o,d^);
}
}
o->maintain();
}
struct point{
int x1,x2,y1,y2,z;
int op,q;
point(int x1=,int y1=,int x2=, int y2=,int z=, int op=, int q=){
this->x1=x1;this->y1=y1; this->x2=x2;this->y2=y2; this->z=z;
this->op=op; this->q=q; }
}P[maxn*],s1[maxn*];
int cntx[maxn*],ans[maxn],point_cnt,x_cnt;
bool vis[maxn];
bool cmp(point A, point B){
if(A.z!=B.z)return A.z<B.z;
return A.q<B.q;
}
int lowbit(int x){
return x&(-x);
}
void add(int loc, int y){
while(loc<=x_cnt){
if( now[ loc ] != Time ){
if(T[loc]!=NULL)removetree(T[loc]);
T[loc]=NULL;
now[loc]=Time;
}
insert(T[loc],y);
loc+=lowbit(loc);
}
}
int search(Node *&o , int y){
if(o==NULL) return ;
if(y<o->y) return search(o->ch[],y);
else {
int a=search(o->ch[],y);
if(o->ch[]!=NULL)
a+=o->ch[]->spoint;
a+=o->loc;
return a;
}
}
int sum(int loc, int y){
int ans=;
while(loc>){
if(now[loc]==Time) ans+=search(T[loc],y);
loc-=lowbit(loc);
}
return ans;
}
void cdq_fz(int L, int R){
if(L>=R) return ;
int mid=(L+R)/;
int e=;
cdq_fz( L, mid );
cdq_fz( mid+, R );
for(int i=L; i<=mid; ++i)
if(P[i].q==) s1[e++]=P[i];
for(int i=mid+; i<=R; ++i)
if(P[i].q!=) s1[e++]=P[i];
sort(s1,s1+e,cmp);
Time++;
for(int i=; i<e; ++i)
if(s1[i].q==){
add(s1[i].x2,s1[i].y2);
}else{
ans[s1[i].q]+=s1[i].op*sum(s1[i].x2, s1[i].y2);
ans[s1[i].q]-=s1[i].op*sum(s1[i].x1, s1[i].y2);
ans[s1[i].q]-=s1[i].op*sum(s1[i].x2, s1[i].y1);
ans[s1[i].q]+=s1[i].op*sum(s1[i].x1, s1[i].y1);
}
}
void solve(){
int N;
scanf("%d",&N);
for(int cc=; cc<=N; ++cc){
int op,x1,x2,y1,y2,z1,z2;
scanf("%d",&op);
if(op==){
scanf("%d%d%d",&x1,&y1,&z1);
P[point_cnt++]=point(x1,y1,x1,y1,z1,,);
cntx[x_cnt++]=x1;
vis[cc]=false;
}else{
scanf("%d%d%d%d%d%d",&x1,&y1,&z1,&x2,&y2,&z2);
cntx[x_cnt++]=x1-;
cntx[x_cnt++]=x2;
P[point_cnt++]=point(x1-,y1-,x2,y2, z2, ,cc);
P[point_cnt++]=point(x1-,y1-,x2,y2,z1-,-,cc);
vis[cc]=true;
}
}
sort(cntx,cntx+x_cnt);
x_cnt=unique(cntx,cntx+x_cnt)-cntx;
for(int i= ; i<point_cnt ; ++i ){
if(P[i].q!=)
P[i].x1=lower_bound(cntx,cntx+x_cnt, P[i].x1)-cntx+;
P[i].x2=lower_bound(cntx,cntx+x_cnt, P[i].x2)-cntx+;
}
cdq_fz(,point_cnt-);
for( int i=; i<=N; ++i )
if( vis[i] ) printf("%d\n",ans[i]);
}
int main()
{
int T;
scanf("%d",&T);
while(T--){
memset(ans,,sizeof(ans));
memset(now,,sizeof(now));
x_cnt = point_cnt=;
Time=;
solve();
}
return ;
}

hdu 5126 cdq+Treap+BIT的更多相关文章

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

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

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

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

  3. HDU - 5126 stars (CDQ分治)

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

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

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

  5. HDU - 5126: stars (求立方体内点数 CDQ套CDQ)

    题意:现在给定空空的三维平面,有加点操作和询问立方体点数. 思路:考虑CDQ套CDQ.复杂度是O(NlogN*logN*logN),可以过此题. 具体的,这是一个四维偏序问题,4维分别是(times, ...

  6. hdu 4585 Shaolin treap

    Shaolin Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Problem ...

  7. hdu 5493 Queue treap实现将元素快速插入到第i个位置

    input T 1<=T<=1000 n 1<=n<=100000 h1 k1 h2 k2 ... ... hn kn 1<=hi<=1e9  0<=ki&l ...

  8. HDU - 4456 cdq

    题意:给一个矩阵,两种操作1:修改单点的权值,2:查询和某个点曼哈顿距离小于r点的权值和 题解:先旋转坐标轴,(x,y)->(x-y,x+y)然后就变成了cdq分治裸题,子矩阵和和单点修改一维时 ...

  9. HDU 4585 平衡树Treap

    点击打开链接 题意:给出n组数,第一个数是id.第二个数是级别.每输入一个.输出这个人和哪个人打架,这个人会找和他级别最相近的人打,假设有两个人级别和他相差的一样多,他就会选择级别比他小的打架. 思路 ...

随机推荐

  1. 图->存储结构->邻接表

    文字描述 邻接表是图的一种链式存储结构.在邻接表中,对图中每个顶点建立一个单链表,第i个单链表的结点表示依附顶点vi的边(对有向图是指以顶点vi为尾的弧).单链表中的每个结点由3个域组成,其中邻接点域 ...

  2. delphi连接mysql (通过libmysql.dll连接)

    首先在窗体上拖拽sqlconnection和sqlquery两个控件: 然后在测试连接中,写入以下代码(注意exe生成目录下需要有dbxopenmysql50.dll和libmysql.dll) SQ ...

  3. Celery 出现Process 'Worker-5' pid:5608 exited with 'exitcode 1' 问题

    起初我以为是进程PID文件问题,从新删除问题并未解决. 现已解决办法公布如下: pip install --upgrade billiard 原因:依赖的billiard库版本有点低,更新即可

  4. git的配置操作

    git配置信息 一.配置git config git config user.name 'yourName' git config user.name 'yourEmail@gmail.com' 二. ...

  5. 帝国cms支持的变量及灵动标签变量汇总

    帝国CMS对首页.列表页.内容页这三个页面模板支持的变量是不同的,有的是通用的,有的不是通用的,本文就这三个模板常用的变量列于此,另外灵动标签很好用啊,也顺便收藏于此,以备后用,到时不用到处翻来翻去的 ...

  6. ERROR 1153 (08S01): Got a packet bigger than 'max_allowed_packet' bytes怎么处理

    今天ytkah进行了应急数据库恢复,用Navicat for Mysql导入sql文件出现ERROR 1153 (08S01): Got a packet bigger than 'max_allow ...

  7. jmeter测试文件上传接口报错:connection reset by peer: socket write error

    最近在对文件上传接口性能测试时,设置150线程数并发时,总会出现以下错误:connection reset by peer: socket write error 在网上搜索了一下,得到的原因有这些: ...

  8. Python基础-编码与解码

      一.什么是编码 编码是指信息从一种形式或格式转换为另一种形式或格式的过程. 在计算机中,编码,简而言之,就是将人能够读懂的信息(通常称为明文)转换为计算机能够读懂的信息.众所周知,计算机能够读懂的 ...

  9. 发现Boost官方文档的一处错误(numpy的ndarray)

    文档位置:https://www.boost.org/doc/libs/1_65_1/libs/python/doc/html/numpy/tutorial/ndarray.html shape在这里 ...

  10. 浅谈Python web框架

    一.Python web框架 Web Framework,Ruby的世界Rails一统江湖,而Python则是一个百花齐放的世界,各种micro-framework.framework不可胜数,不完全 ...