离线所有操作,对所有可能存在的点建立kd-tree,add相当于权值+1,cancel相当于权值-1。
修改操作要记录kd-tree上每个点的fa,从底向上地进行修改。
优化:若一个矩形框的sumv==0,则不进入。记录矩形框的面积时只记录“有意义”的点的(权值为0的不管)。
#include<cstdio> #include<algorithm> #include<stack> #include<cstring> using namespace std; int f,C; inline void R(int &x){ C=0;f=1; for(;C<‘0‘||C>‘9‘;C=getchar())if(C==‘-‘)f=-1; for(x=0;C>=‘0‘&&C<=‘9‘;C=getchar())(x*=10)+=(C-‘0‘); x*=f; } inline void P(int x){ if(x<10)putchar(x+‘0‘); else{P(x/10);putchar(x%10+‘0‘);} } stack<int>zhan; #define N 100001 #define KD 3 int dn,n,root,m,qp[2][KD],idn; struct Node { int ch[2],w,minn[KD],maxx[KD],p[KD],sumv,id; void Init() { sumv=w; for(int i=0;i<KD;++i) minn[i]=maxx[i]=p[i]; } }T[N]; bool operator < (const Node &a,const Node &b){return a.p[dn] < b.p[dn];} inline void pushup(const int &rt) { T[rt].sumv=T[rt].w; for(int i=0;i<2;++i) if(T[rt].ch[i]/* && T[T[rt].ch[i]].sumv*/) { T[rt].sumv+=T[T[rt].ch[i]].sumv; for(int j=0;j<KD;++j) { T[rt].minn[j]=min(T[rt].minn[j],T[T[rt].ch[i]].minn[j]); T[rt].maxx[j]=max(T[rt].maxx[j],T[T[rt].ch[i]].maxx[j]); } } } int buildtree(int l=1,int r=n,int d=0) { dn=d; int m=(l+r>>1); nth_element(T+l,T+m,T+r+1); T[m].Init(); if(l!=m) T[m].ch[0]=buildtree(l,m-1,(d+1)%KD); if(m!=r) T[m].ch[1]=buildtree(m+1,r,(d+1)%KD); pushup(m); return m; } inline bool Inside(const int &o) { for(int i=0;i<KD;++i) if(qp[0][i] > T[o].p[i] || T[o].p[i] > qp[1][i]) return 0; return 1; } inline bool AllInside(const int &o) { for(int i=0;i<KD;++i) if(qp[0][i] > T[o].minn[i] || T[o].maxx[i] > qp[1][i]) return 0; return 1; } inline bool Cross(const int &o) { for(int i=0;i<KD;++i) if(qp[0][i] > T[o].maxx[i] || T[o].minn[i] > qp[1][i]) return 0; return 1; } int ans; inline void Query(int rt=root) { if(Inside(rt)) ans+=T[rt].w; for(int i=0;i<2;++i) if(T[rt].ch[i] && Cross(T[rt].ch[i])) { if(AllInside(T[rt].ch[i])) ans+=T[T[rt].ch[i]].sumv; else if(T[T[rt].ch[i]].sumv) Query(T[rt].ch[i]); } } int val; char op[N][7]; int dian[N][KD],rs[N],ids[N],ma[N],fa[N]; void Update() { int U=ma[idn]; T[U].w+=val; T[U].sumv+=val; U=fa[U]; while(U) { T[U].sumv=T[U].w+T[T[U].ch[0]].sumv+T[T[U].ch[1]].sumv; // pushup(U); U=fa[U]; } } int main() { // freopen("theresa9.in","r",stdin); // freopen("bzoj3290.out","w",stdout); R(n); for(int i=1;i<=n;++i) { R(T[i].p[0]); R(T[i].p[1]); R(T[i].p[2]); T[i].id=i; T[i].w=1; } R(m); for(int i=1;i<=m;++i) { scanf("%s",op[i]); if(op[i][0]==‘A‘) { ++n; R(T[n].p[0]); R(T[n].p[1]); R(T[n].p[2]); T[n].id=n; ids[i]=n; zhan.push(n); } else if(op[i][0]==‘Q‘) { R(dian[i][0]); R(dian[i][1]); R(dian[i][2]); R(rs[i]); } else { ids[i]=zhan.top(); zhan.pop(); } } root=(1+n>>1); buildtree(); for(int i=1;i<=n;++i) { ma[T[i].id]=i; for(int j=0;j<2;++j) if(T[i].ch[j]) fa[T[i].ch[j]]=i; } for(int i=1;i<=m;++i) if(op[i][0]==‘A‘) { idn=ids[i]; val=1; Update(); } else if(op[i][0]==‘Q‘) { memcpy(qp[0],dian[i],sizeof(qp[0])); for(int j=0;j<KD;++j) qp[1][j]=qp[0][j]+rs[i]; ans=0; Query(); // printf("%d\n",ans); P(ans),puts(""); } else { idn=ids[i]; val=-1; Update(); } return 0; }
时间: 2024-11-05 19:45:48