您的位置:首页 > 其它

hdu 5126 cdq+Treap+BIT

2015-08-01 23:34 225 查看
这题说的是给了三维空间然后操作 寻求在 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>
#include <cstdlib>
using namespace std;
const int maxn=50000+10;
struct Node{
Node *ch[2];
int r;
int y;
int spoint;
int loc;
void maintain(){
spoint=loc;
if(ch[0]!=NULL) spoint+=ch[0]->spoint;
if(ch[1]!=NULL) spoint+=ch[1]->spoint;
}
Node(int v):y(v){ r=rand(); spoint=1; loc=1; ch[0]=ch[1]=NULL; }
int cmp(int x){
if(x==y) return -1;
return x<y?0:1;
}
};
Node *T[maxn*3];
int now[maxn*3],Time;
void removetree(Node *&o){
if(o->ch[0]!=NULL) removetree(o->ch[0]);
if(o->ch[1]!=NULL) removetree(o->ch[1]);
delete o;
o=NULL;
}
void rotate(Node *&o, int d){
Node *k=o->ch[d^1]; o->ch[d^1]=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==-1){
o->loc++;
}else{
insert(o->ch[d],y);
if( o->ch[d]->r > o->r ) rotate(o,d^1);
}
}
o->maintain();
}
struct point{
int x1,x2,y1,y2,z;
int op,q;
point(int x1=0,int y1=0,int x2=0, int y2=0,int z=0, int op=0, int q=0){
this->x1=x1;this->y1=y1; this->x2=x2;this->y2=y2; this->z=z;
this->op=op; this->q=q;

}
}P[maxn*3],s1[maxn*3];
int cntx[maxn*3],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 0;
if(y<o->y) return search(o->ch[0],y);
else {
int a=search(o->ch[1],y);
if(o->ch[0]!=NULL)
a+=o->ch[0]->spoint;
a+=o->loc;
return a;
}
}
int sum(int loc, int y){
int ans=0;
while(loc>0){
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)/2;
int e=0;
cdq_fz(     L, mid );
cdq_fz( mid+1,   R );
for(int i=L; i<=mid; ++i)
if(P[i].q==0) s1[e++]=P[i];
for(int i=mid+1; i<=R; ++i)
if(P[i].q!=0) s1[e++]=P[i];
sort(s1,s1+e,cmp);
Time++;
for(int i=0; i<e; ++i)
if(s1[i].q==0){
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=1; cc<=N; ++cc){
int op,x1,x2,y1,y2,z1,z2;
scanf("%d",&op);
if(op==1){
scanf("%d%d%d",&x1,&y1,&z1);
P[point_cnt++]=point(x1,y1,x1,y1,z1,1,0);
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-1;
cntx[x_cnt++]=x2;
P[point_cnt++]=point(x1-1,y1-1,x2,y2,  z2, 1,cc);
P[point_cnt++]=point(x1-1,y1-1,x2,y2,z1-1,-1,cc);
vis[cc]=true;
}
}
sort(cntx,cntx+x_cnt);
x_cnt=unique(cntx,cntx+x_cnt)-cntx;
for(int i=0 ; i<point_cnt ; ++i ){
if(P[i].q!=0)
P[i].x1=lower_bound(cntx,cntx+x_cnt,  P[i].x1)-cntx+1;
P[i].x2=lower_bound(cntx,cntx+x_cnt,  P[i].x2)-cntx+1;
}
cdq_fz(0,point_cnt-1);
for( int i=1; i<=N; ++i )
if( vis[i] ) printf("%d\n",ans[i]);
}
int main()
{
int T;
scanf("%d",&T);
while(T--){
memset(ans,0,sizeof(ans));
memset(now,0,sizeof(now));
x_cnt = point_cnt=0;
Time=1;
solve();
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: