关于KDT剪枝的有关问题
查看原帖
关于KDT剪枝的有关问题
390742
qwqUwU楼主2022/7/13 17:58

求助。 想问一下 KDT 做偏序的时候有哪些比较强力的剪枝方法。

另附我 60pts 的代码,TLE 了最后两个点,其余全 AC。

#include<bits/stdc++.h>
#define ll long long
#define mid (l+r>>1)
#define ls(x) t[x].son[0]
#define rs(x) t[x].son[1]
const int N=5e4+10; 
const double alpha=0.75;
using namespace std;
inline ll read(){
	ll x=0,f=1,c=getchar();
	while(c<'0'||c>'9')f=(c=='-'?-1:1),c=getchar();
	while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x*f;
}
struct Tree{
	ll P[4],Min[4],Max[4],val,dp,size,maxn;
	int son[2],d;
	Tree(){
		son[0]=son[1]=0;
		d=size=1;
	}
	void init(){
		for(int i=0;i<4;i++)Min[i]=Max[i]=P[i]=read();
		dp=maxn=val=read();
	}
	void clear(){
		for(int i=1;i<4;i++)Min[i]=Max[i]=P[i];
		son[0]=son[1]=0;
		maxn=dp;
		d=size=1;
	}
}t[N];
int n,root,D,rub[N],cnt,tot;
inline void update(int x){
	t[x].maxn=max(t[x].maxn,t[x].dp);
	if(ls(x)){
		for(int i=1;i<4;i++){
			t[x].Min[i]=min(t[x].Min[i],t[ls(x)].Min[i]);
			t[x].Max[i]=max(t[x].Max[i],t[ls(x)].Max[i]);
		}
		t[x].maxn=max(t[x].maxn,t[ls(x)].maxn);
		t[x].size+=t[ls(x)].size;
	}
	if(rs(x)){
		for(int i=1;i<4;i++){
			t[x].Min[i]=min(t[x].Min[i],t[rs(x)].Min[i]);
			t[x].Max[i]=max(t[x].Max[i],t[rs(x)].Max[i]);
		}
		t[x].maxn=max(t[x].maxn,t[rs(x)].maxn);
		t[x].size+=t[rs(x)].size;
	}
}
inline bool Cmp(int x,int y){
	return t[x].P[D]<t[y].P[D];
}
inline int build(int l,int r){
	if(l>r)return 0;
	double avr[4]={0},var[4]={0};
	for(int i=l;i<=r;i++)
		for(int j=1;j<4;j++)
			avr[j]+=t[rub[i]].P[j];
	for(int j=1;j<4;j++)avr[j]/=1.0*(r-l+1);
	for(int i=l;i<=r;i++)
		for(int j=1;j<4;j++)
			var[j]+=(t[rub[i]].P[j]-avr[j])*(t[rub[i]].P[j]-avr[j]);
	if(max({var[1],var[2],var[3]})==var[1])D=t[rub[mid]].d=1;
	if(max({var[1],var[2],var[3]})==var[2])D=t[rub[mid]].d=2;
	if(max({var[1],var[2],var[3]})==var[3])D=t[rub[mid]].d=3;
	nth_element(rub+l,rub+mid,rub+r+1,Cmp);
	ls(rub[mid])=build(l,mid-1);
 	rs(rub[mid])=build(mid+1,r);
	update(rub[mid]);
	return rub[mid];
}
inline void Del(int x){
	if(!x)return ;
	Del(ls(x)),Del(rs(x));
	t[x].clear();
	rub[++cnt]=x;
}
inline void rebuild(int &x){
	cnt=0;
	Del(x);
	x=build(1,cnt);
}
inline bool cmp(Tree a,Tree b){
	for(int i=0;i<4;i++)
		if(a.P[i]!=b.P[i])
			return a.P[i]<b.P[i];
}
inline void Insert(int u,int &x=root){
	if(!x){
		x=++tot;
		update(x);
		return;
	}
	D=t[x].d;
	if(t[u].P[D]<t[x].P[D])Insert(u,ls(x));
	else Insert(u,rs(x));
	update(x);
	if(t[x].size*alpha<max(t[ls(x)].size,t[rs(x)].size))rebuild(x);
}
inline void query(int u,int x=root){
	if(!x)return;
	for(int i=1;i<4;i++)
		if(t[u].P[i]<t[x].Min[i])
			return ;
	if(t[x].maxn+t[u].val<=t[u].dp)return;
	bool flag=1;
	for(int i=1;i<4;i++)
		if(t[u].P[i]<t[x].Max[i])
			flag=0;
	if(flag){
		t[u].dp=t[x].maxn+t[u].val;
		return ;
	}
	flag=1;
	for(int i=1;i<4;i++)
		if(t[u].P[i]<t[x].P[i])
			flag=0;
	if(flag)t[u].dp=max(t[u].dp,t[x].dp+t[u].val);
	query(u,ls(x)),query(u,rs(x));
}
int main(){
	freopen("data.in","r",stdin);
//	freopen("data.out","w",stdout);
	n=read();
	for(int i=1;i<=n;i++)t[i].init();
	int cur=0;
	for(int i=1;i<=n;i++)
		if(t[i].val>0)
			t[++cur]=t[i];
	if(!cur){
		ll ans=t[1].val;
		for(int i=2;i<=n;i++)ans=max(ans,t[i].val);
		printf("%lld",ans);
		return 0;
	}
	n=cur;
	sort(t+1,t+n+1,cmp);
	for(int i=1;i<=n;i++){
		query(i);
		Insert(i);
	}
	ll ans=0;
	for(int i=1;i<=n;i++)ans=max(ans,t[i].dp);
	printf("%lld",ans);
	return 0;
}
/*
4
1 1 1 1 1
2 2 2 2 2
3 3 3 3 3
4 4 4 4 4
*/
2022/7/13 17:58
加载中...