HDU5126 stars题解

HDU5126

Description

\(T\) 组数据,给一个空的三维空间,\(Q\) 次操作,分为插入一个点和查询某个立方体内点的个数。

\(T \le 10,Q \le 5 \times 10^4\)

Sol

题目没说强制在线那先离线下来再说。

然后可以娴熟的把询问操作用差分变成八个子问题。

然后就会发现这是个偏序问题,每一个点有四个属性(三维坐标,插入时间)。对于一个询问,对它的答案有贡献的点是三维坐标均小于它本身且比它早插入的点。

于是四维偏序套三层CDQ分治就好了。当然两层CDQ加树状数组也行但是要注意离散化。

时间复杂度 \(\mathrm{O}(n \log^3 n)\)

调了两天,累死咯。

Hint

  • 数组开八倍。
  • 多测不清空,爆零两行泪。

Code

#include<cstdio>
#include<algorithm>
#include<cstring>
using std::sort;
const int M=5e4+5;
inline int read(){int x(0),op(0);char ch=getchar();while(ch<'0'||ch>'9')op|=(ch==45),ch=getchar();while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();return op?-x:x;}
inline int ssread(){int x;scanf("%d",&x);return x;}
#ifndef ONLINE_JUDGE
#define read ssread
#endif
struct node{
	int a,b,c,d,t;
}a[M<<3],b[M<<3],c[M<<3],tmp[M<<3];
bool cmpa(node x,node y){return x.a!=y.a?x.a<y.a:x.t<y.t;}
bool cmpb(node x,node y){return x.b!=y.b?x.b<y.b:x.t<y.t;}
bool cmpc(node x,node y){return x.c!=y.c?x.c<y.c:x.t<y.t;}
int Ans[M<<4],n,m,qt;
void solve3(int l,int r){
	if(l>=r)return;
	int mid=l+r>>1;
	solve3(l,mid);solve3(mid+1,r);
	int i=l,p=l;
	for(int j=mid+1,cnt=0;j<=r;){
		while(i<=mid&&c[i].d<=c[j].d){
			if(!c[i].t)cnt++;
			tmp[p++]=c[i++];
		}
		if(c[j].t)Ans[c[j].t]+=cnt;
		tmp[p++]=c[j++];
	}
	while(i<=mid)tmp[p++]=c[i++];
	for(i=l;i<=r;++i)c[i]=tmp[i];
}
void solve2(int l,int r){
	if(l>=r)return;
	int mid=l+r>>1,n=0;
	solve2(l,mid);solve2(mid+1,r);
	for(int i=l;i<=mid;++i)if(!b[i].t)c[++n]=b[i];
	for(int i=mid+1;i<=r;++i)if(b[i].t)c[++n]=b[i];
	sort(c+1,c+n+1,cmpc);
	solve3(1,n);
}
void solve1(int l,int r){
	if(l>=r)return;
	int mid=l+r>>1,n=0;
	solve1(l,mid);solve1(mid+1,r);
	for(int i=l;i<=mid;++i)if(!a[i].t)b[++n]=a[i];
	for(int i=mid+1;i<=r;++i)if(a[i].t)b[++n]=a[i];
	sort(b+1,b+n+1,cmpb);
	solve2(1,n);
}
void addp(int x,int y,int z,int w,int t){
	a[++n]=(node){x,y,z,w,t};
}
void work(){
	m=read();n=0;qt=0;
	memset(Ans,0,sizeof(Ans));
	for(int i=1,x[2],y[2],z[2];i<=m;++i){
        int op=read();x[1]=read(),y[1]=read(),z[1]=read();
        if(op==1)addp(x[1],y[1],z[1],i,0);
        else{
            qt++;
            x[0]=read(),y[0]=read(),z[0]=read();
            x[1]--;y[1]--;z[1]--;
            for(int k=0;k<8;++k)addp(x[bool(k&1)],y[bool(k&2)],z[bool(k&4)],i,qt+M*k);
        }
    }
	sort(a+1,a+n+1,cmpa);
	solve1(1,n);
	for(int i=1;i<=qt;++i){
        int ans=0;
        for(int j=0;j<8;++j)ans+=(__builtin_popcount(j)&1?-1:1)*Ans[j*M+i];
        printf("%d\n",ans);
    }
}
int main(){
	int T=read();
	while(T--)work();
	return 0;
}
posted @ 2023-02-07 20:36  pokefunc  阅读(48)  评论(0)    收藏  举报