3:查询当前空间中,(x,y,z)
(
x
,
y
,
z
)
~(x+r,y+r,z+r)
(
x
+
r
,
y
+
r
,
z
+
r
)
正方体中的点
想法:
猥琐的数据结构~~
先讲讲扫描线,即在二维平面中,已知某些点,查询某个矩形的权值和
先将x
x
坐标从小到大排序,然后遇到一个点,我们就给线段树or树状数组对应的位置加上相应的权值,对于查询矩阵(x1
x
1
~x2
x
2
)(y1
y
1
~y2
y
2
),我们就可以用ans
a
n
s
(1
1
~x2)(y1
y
1
~y2
y
2
)-ans
a
n
s
(1
1
~x1−1)(y1
y
1
~y2
y
2
),即在扫描到x1−1
x
1
−
1
时求出此时(y1
y
1
~y2
y
2
)的答案,再扫描到x2
x
2
时求出此时(y1
y
1
~y2
y
2
)的答案,相减即可
万一边加点边查询呢,如何解决
考虑cdq分治
我们可以先以时间为第一关键字排序,然后对于区间(l
(
l
~r)
r
)
,当前仅仅考虑(l
(
l
~mid)
m
i
d
)
中加点操作
对(mid+1
(
m
i
d
+
1
~r)
r
)
中询问的影响,然后用扫描线解决,在递归进入(l
(
l
~mid)
m
i
d
)
,(mid+1
(
m
i
d
+
1
~r)
r
)
分别解决子问题
其实可以在cdq分治时用归并排序对x排序,到时加点判断时间<=mid
<=
m
i
d
<script type="math/tex" id="MathJax-Element-95"><=mid</script>才做,查询>mid
>
m
i
d
才做,优化时间
然后在考虑这题
一种是cdq套cdq,但我不会~
还有一种是用cdq对时间分治,
用归并排序对x排序,进行扫描线
然后遇到点(x,y,z)
(
x
,
y
,
z
)
,就在平面(y,z)
(
y
,
z
)
加上相应的权值,对于询问(x1
(
x
1
~x2,y1
x
2
,
y
1
~y2,z1
y
2
,
z
1
~z2)
z
2
)
,就相当于求ans(1
a
n
s
(
1
~x2,y1
x
2
,
y
1
~y2,z1
y
2
,
z
1
~z2)−ans(1
z
2
)
−
a
n
s
(
1
~x1−1,y1
x
1
−
1
,
y
1
~y2,z1
y
2
,
z
1
~z2)
z
2
)
然后我们需要一个二维数据结构支持插入和询问
带修主席树是一个好东东
如果单纯用主席树,那么我们要给(y
(
y
~n)
n
)
的线段树的第z
z
位加上相应的权值,时间复杂度巨大~~
主席树的第i棵存储的是1~i
i
的信息,那么我们可以用树状数组套线段树
对于第i棵线段树,我们存储的是i−lowbit(i)+1~i
i
的信息(树状数组),这样就不断修改第i+lowbit(i)棵线段树,最后查询同理
记得离散化 时间复杂度(nlog3n
n
l
o
g
3
n
)
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define min(a,b) ((a)<(b)?(a):(b))#define max(a,b) ((a)>(b)?(a):(b))#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
const int maxN=2e5+10,maxx=31250000,maxn=1e7;
struct zhj{
intx,y,z,zz,yy,zl,wz;
}a[maxN],b[maxN],c[maxN*2];
struct xkq{
int x,l,r;
}tr[maxx];
char ch;
int n,m,i,j,pre[maxN],answer[maxN],fro[maxN],q,tot,cnt,zl,ans,
xxl,xxr,yyl,yyr,sum,rr,mz,my,tail,tail1,root[maxN];
bool cmp(zhj x,zhj y){
return ((x.x<y.x) ||(x.x==y.x && x.zl<y.zl));
}
void scan(){
scanf("%d",&n);
fo(i,1,n) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z),a[i].zl=1,a[i].wz=i,pre[++pre[0]]=i,my=max(a[i].y,my),mz=max(a[i].z,mz);
scanf("%d\n",&q),cnt=n;
fo(i,1,q){
scanf("%c",&ch);
if (ch=='A'){
cnt++;
scanf("DD %d%d%d\n",&a[cnt].x,&a[cnt].y,&a[cnt].z);
a[cnt].wz=cnt,a[cnt].zl=1,pre[++pre[0]]=cnt;
my=max(a[cnt].y,my),mz=max(a[cnt].z,mz);
}
if (ch=='C'){
cnt++;
scanf("ANCEL\n");
a[cnt]=a[pre[pre[0]]];
a[cnt].wz=cnt,a[cnt].zl=-1;
pre[0]--;
}
if (ch=='Q') {
cnt++;
scanf("UERY %d%d%d%d\n",&a[cnt].x,&a[cnt].y,&a[cnt].z,&rr);
a[cnt].wz=cnt,a[cnt].zl=2,fro[cnt]=++answer[0],a[cnt].yy=a[cnt].y+rr,a[cnt].zz=a[cnt].z+rr;
a[cnt].x--;
a[cnt+1]=a[cnt];
a[++cnt].x+=rr+1,a[cnt].wz=cnt,a[cnt].zl=3,fro[cnt]=answer[0];
}
}
fo(i,1,cnt)
a[i].yy=min(a[i].yy,my),a[i].zz=min(a[i].zz,mz);
tot=0;
fo(i,1,cnt){
c[++tot].x=a[i].y,c[tot].wz=i,c[tot].zl=0;
if (a[i].zl>1)
c[++tot].x=a[i].yy,c[tot].wz=i,c[tot].zl=1;
}
sort(c+1,c+tot+1,cmp);
if (c[1].zl==0) a[c[1].wz].y=sum=1;
else a[c[1].wz].yy=sum=1;
fo(i,2,tot){
if (c[i].x>c[i-1].x) sum++;
if (c[i].zl==0) a[c[i].wz].y=sum;
else a[c[i].wz].yy=sum;
}
my=sum,tot=0;
fo(i,1,cnt){
c[++tot].x=a[i].z,c[tot].wz=i,c[tot].zl=0;
if (a[i].zl>1)
c[++tot].x=a[i].zz,c[tot].wz=i,c[tot].zl=1;
}
sort(c+1,c+tot+1,cmp);
if (c[1].zl==0) a[c[1].wz].z=sum=1;
else a[c[1].wz].zz=sum=1;
fo(i,2,tot){
if (c[i].x>c[i-1].x) sum++;
if (c[i].zl==0) a[c[i].wz].z=sum;
else a[c[i].wz].zz=sum;
}
mz=sum;
}
int lowbit(intx){
returnx&(-x);
}
void insert(intx,int head,int tail){
tr[x].x+=zl;
if (head==tail) return;
int mid=(head+tail)/2;
if (yyl<=mid){
if (!tr[x].l) tr[x].l=++cnt;
insert(tr[x].l,head,mid);
}else{
if (!tr[x].r) tr[x].r=++cnt;
insert(tr[x].r,mid+1,tail);
}
}
void query(intx,int head,int tail){
if (yyl<=head && tail<=yyr){sum+=tr[x].x;return;}
int mid=(head+tail)/2;
if (yyl<=mid && tr[x].l) query(tr[x].l,head,mid);
if (mid<yyr && tr[x].r) query(tr[x].r,mid+1,tail);
}
void ins(intx){
while (x<=my){
if(!root[x]) root[x]=++cnt,pre[++pre[0]]=x;
insert(root[x],1,mz);
x+=lowbit(x);
}
}
int find(intx){
sum=0;
while (x){
if (root[x])
query(root[x],1,mz);
x-=lowbit(x);
}
return sum;
}
void work(intx){
cnt=0;
fo(i,1,tot){
if (b[i].zl==1 || b[i].zl==-1){
if (b[i].wz>x) continue;
xxl=xxr=b[i].y,yyl=yyr=b[i].z,zl=b[i].zl;
ins(xxl);
}else{
if (b[i].wz<=x) continue;
xxl=b[i].y,xxr=b[i].yy,yyl=b[i].z,yyr=b[i].zz,zl=0,ans=0;
ans=find(xxr)-find(xxl-1);
if (b[i].zl==2)
answer[fro[b[i].wz]]-=ans;
else answer[fro[b[i].wz]]+=ans;
}
}
fo (i,1,cnt) tr[i].x=tr[i].l=tr[i].r=0;
fo(i,1,pre[0]) root[pre[i]]=0;
pre[0]=0;
}
void cdq(int l,int r){
if (l==r)return;
int mid=(l+r)/2,i,cnt1=0,cnt2=0,cnt3=0;
fo(i,l,mid)
if (a[i].zl==1 || a[i].zl==-1) cnt3++;
fo(i,mid+1,r)
if (a[i].zl>1) cnt2++;
cdq(l,mid);
cdq(mid+1,r);
tail=l,tail1=mid+1,cnt1=0;
while (tail<=mid || tail1<=r){
if (tail>mid) b[++cnt1]=a[tail1],tail1++;
elseif (tail1>r) b[++cnt1]=a[tail],tail++;
else{
if (a[tail].x<=a[tail1].x) b[++cnt1]=a[tail],tail++;
else b[++cnt1]=a[tail1],tail1++;
}
}
fo(i,l,r) a[i]=b[i-l+1];
tot=cnt1;
if (!(cnt3 && cnt2)) return;
work(mid);
}
void prin(){
//printf("%d\n",sum);
fo(i,1,answer[0])
printf("%d\n",answer[i]);
}
int main(){
//freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
scan();
cdq(1,cnt);
prin();
}