求助。 想问一下 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
*/