大意:
向三维空间中加点,询问一个三维区间中点的个数。
解题思路:
带修改CDQ,将修改和询问一起插入CDQ分治询问。
(询问可以由8个前缀和加减操作实现)
其中第一层CDQ维护x有序。
第二层CDQ维护y有序并且将z离线处理完更新答案。
注意要将原数组的辅助数组推入第二层CDQ否则会将顺序毁坏。
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 const int N=1000001; 5 const int M=4000001; 6 struct data{ 7 int t; 8 int x; 9 int y; 10 int tz; 11 int z; 12 int c; 13 bool left; 14 }d[N],o[N],tmp[N],stdata; 15 int n,T; 16 int cnt; 17 int tot; 18 int ans[N]; 19 int sek[N]; 20 int line[M]; 21 bool cmpz(data a,data b){return a.tz<b.tz;} 22 bool cmpb(data a,data b){return a.t<b.t;} 23 int lowbit(int x){return x&(-x);} 24 void update(int pos,int v) 25 { 26 while(pos<=tot) 27 { 28 line[pos]+=v; 29 pos+=lowbit(pos); 30 } 31 return ; 32 } 33 int query(int pos) 34 { 35 int ans=0; 36 while(pos) 37 { 38 ans+=line[pos]; 39 pos-=lowbit(pos); 40 } 41 return ans; 42 } 43 void Get(void) 44 { 45 tot=1; 46 std::sort(d+1,d+cnt+1,cmpz); 47 d[1].z=1; 48 for(int i=2;i<=cnt;i++) 49 { 50 if(d[i].tz!=d[i-1].tz) 51 tot++; 52 d[i].z=tot; 53 } 54 std::sort(d+1,d+cnt+1,cmpb); 55 return ; 56 } 57 void cdq(int l,int r) 58 { 59 if(l==r) 60 return ; 61 int mid=(l+r)>>1; 62 cdq(l,mid); 63 cdq(mid+1,r); 64 int j=l; 65 for(int i=mid+1;i<=r;i++) 66 { 67 for(;j<=mid&&o[j].y<=o[i].y;j++) 68 if(!o[j].c&&o[j].left) 69 update(o[j].z,1); 70 if(o[i].left) 71 continue; 72 ans[o[i].t]+=o[i].c*query(o[i].z); 73 } 74 for(int i=l;i<j;i++) 75 if(!o[i].c&&o[i].left) 76 update(o[i].z,-1); 77 int sta1=l,sta2=mid+1; 78 for(int i=l;i<=r;i++) 79 if(sta1<=mid&&(sta2>r||o[sta1].y<=o[sta2].y)) 80 tmp[i]=o[sta1++]; 81 else 82 tmp[i]=o[sta2++]; 83 for(int i=l;i<=r;i++) 84 o[i]=tmp[i]; 85 return ; 86 } 87 void CDQ(int l,int r) 88 { 89 if(l==r) 90 return ; 91 int mid=(l+r)>>1; 92 CDQ(l,mid); 93 CDQ(mid+1,r); 94 for(int i=l;i<=r;i++) 95 d[i].left=(i<=mid); 96 int sta1=l,sta2=mid+1; 97 for(int i=l;i<=r;i++) 98 if(sta1<=mid&&(sta2>r||d[sta1].x<=d[sta2].x)) 99 o[i]=d[sta1++]; 100 else 101 o[i]=d[sta2++]; 102 for(int i=l;i<=r;i++) 103 d[i]=o[i]; 104 cdq(l,r); 105 for(int i=l;i<=r;i++) 106 d[i].left=false; 107 return ; 108 } 109 int main() 110 { 111 //freopen("a.in","r",stdin); 112 scanf("%d",&T); 113 while(T--) 114 { 115 for(int i=1;i<=n;i++) 116 ans[i]=0; 117 for(int i=1;i<=cnt;i++) 118 d[i]=tmp[i]=stdata; 119 cnt=n=0; 120 scanf("%d",&n); 121 for(int i=1;i<=n;i++) 122 { 123 int cmd; 124 scanf("%d",&cmd); 125 sek[i]=cmd; 126 if(cmd==1) 127 { 128 int x,y,z; 129 scanf("%d%d%d",&x,&y,&z); 130 d[++cnt]=(data){i,x,y,z,0,0,0}; 131 }else{ 132 int ax,ay,az,bx,by,bz; 133 scanf("%d%d%d%d%d%d",&ax,&ay,&az,&bx,&by,&bz); 134 if(ax>bx) 135 std::swap(ax,bx); 136 if(ay>by) 137 std::swap(ay,by); 138 if(az>bz) 139 std::swap(az,bz); 140 ax--,ay--,az--; 141 d[++cnt]=(data){i,ax,ay,az,0,-1,0}; 142 d[++cnt]=(data){i,ax,ay,bz,0,1,0}; 143 d[++cnt]=(data){i,ax,by,az,0,1,0}; 144 d[++cnt]=(data){i,bx,ay,az,0,1,0}; 145 d[++cnt]=(data){i,ax,by,bz,0,-1,0}; 146 d[++cnt]=(data){i,bx,ay,bz,0,-1,0}; 147 d[++cnt]=(data){i,bx,by,az,0,-1,0}; 148 d[++cnt]=(data){i,bx,by,bz,0,1,0}; 149 } 150 } 151 152 Get(); 153 CDQ(1,cnt); 154 for(int i=1;i<=n;i++) 155 if(sek[i]==2) 156 printf("%d ",ans[i]); 157 } 158 return 0; 159 }