hdu 5126 cdq+Treap+BIT
这题说的是给了三维空间然后操作 寻求在 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的更多相关文章
- 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)为左上和右下顶点的矩形之间 ...
- HDU 5126 stars 4维偏序, CDQ套CDQ
题目传送门 题意:在一个星空中,按着时间会出现一些点,现在john想知道,在某个时间内有多少个星星是的坐标是满足条件的.(x1<=x<=x2, y1 <= y <= y2, z ...
- HDU - 5126: stars (求立方体内点数 CDQ套CDQ)
题意:现在给定空空的三维平面,有加点操作和询问立方体点数. 思路:考虑CDQ套CDQ.复杂度是O(NlogN*logN*logN),可以过此题. 具体的,这是一个四维偏序问题,4维分别是(times, ...
- hdu 4585 Shaolin treap
Shaolin Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Problem ...
- 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 ...
- HDU - 4456 cdq
题意:给一个矩阵,两种操作1:修改单点的权值,2:查询和某个点曼哈顿距离小于r点的权值和 题解:先旋转坐标轴,(x,y)->(x-y,x+y)然后就变成了cdq分治裸题,子矩阵和和单点修改一维时 ...
- HDU 4585 平衡树Treap
点击打开链接 题意:给出n组数,第一个数是id.第二个数是级别.每输入一个.输出这个人和哪个人打架,这个人会找和他级别最相近的人打,假设有两个人级别和他相差的一样多,他就会选择级别比他小的打架. 思路 ...
随机推荐
- 最全的MonkeyRunner自动化测试从入门到精通(1)
一.环境变量的配置 1.JDK环境变量的配置 步骤一:在官网上面下载jdk,JDK官网网址: http://www.oracle.com/technetwork/java/javase/downloa ...
- 20165225《Java程序设计》第三周学习总结
20165225<Java程序设计>第三周学习总结 1.视频与课本中的学习: 遇到的问题: 问题如下,无法编译. 最后经同学点出要放在同一个打包的文件夹里,于是就运行成功了,下面是4_15 ...
- 预备作业3:Linux安装及命令入门
linux系统的安装 1.虚拟机: 首先是VirtualBox5.2.7的安装,这个按照老师给的基于VirtualBox安装Ubuntu图文教程一步步来很快就能安好,也没有遇到无法选择64-bit的问 ...
- jquery有几种选择器?
①.基本选择器:#id,class,element,*: ②.层次选择器:parent > child,prev + next,prev ~ siblings: ③.基本过滤器选择器::firs ...
- oracle稳定执行计划(更改)的方法
应用于那些执行计划已经发生了的不好的变更的SQL上(在不改变SQL文本的情况下,改变其执行计划),即便通过创建SQL Profile解决了目标SQL执行计划变更的问题,依然不能保证系统后续执行的SQL ...
- xargs与管道的区别
一.直观感受 echo '--help' | cat echo的输出通过管道定向到cat的输入, 然后cat从其标准输入中读取待处理的文本内容, 输出结果: --help echo '--help' ...
- 009-docker-安装-redis:5.0.3
1.搜索镜像 docker search redis 2.拉取合适镜像 docker pull redis:5.0.3 docker images 3.使用镜像 docker run -p 6379: ...
- MySql语句常用命令整理---单表查询
初始化t_employee表 创建t_employee表 -- DROP TABLE IF EXISTS test; CREATE TABLE t_employee ( _id INTEGER PRI ...
- centos 打包报错License for package Android SDK Build-Tools 25.0.3 not accepted
报错如下: 提示没有25.0.3的安卓环境,那么,接下来就需要安装这个环境 1.android list sdk -a 会显示需要更新 类似如下(截图只是一部分,前后还有一部分): 2.android ...
- 产品设计教程:wireframe,prototype,mockup到底有何不同?
wireframe,prototype,mockup 三者经常被混用,很多人把三者都叫原型,真的是这样吗? 我们来看看三者到底有何不同.先来做一道选择题: 从这张图可以看出,prototype 和其他 ...