首页 > 其他 > 详细

[AHOI2008]矩形藏宝地 (kd-tree)

时间:2019-10-06 21:04:50      阅读:68      评论:0      收藏:0      [点我收藏+]

[AHOI2008]矩形藏宝地

kd-treeTLE成88分时, 看到大佬们用的都是cdq分治, 于是写来一篇靠特判才能过的kd-tree题解

我们可以将一个矩形(x1,y1,x2,y2), 看成是三维空间中的一个坐标为(x1,y1,x2), 点权是y2的点

那么如何判断一个矩形被包含?

对于一个矩形(x1,y1,x2,y2)

当三维空间中(0~x1-1, 0~y1-1, x2+1~\(\infty\))最大点权大于y2时, 说明该矩形被覆盖

考虑到当区域中的最大值小于y2时, 不对答案造成贡献, 因此可以大幅剪枝并获得88分的好成绩

加个O2, 第三个点判判判就能过了╮( ̄▽ ̄)╭

#include<iostream>
#include<algorithm>
using namespace std;
int read(){
    int x=0,f=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
    for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';
    return x*f;
}
const int N=2e5+28;
int D,yi;
class KD_TREE{
private:
public:
    struct POS{
    int d[3],mx[3],mn[3],ls,rs,val,num;
    inline int &operator [] (int a){return d[a];}
    inline friend bool operator < (POS a,POS b){
        return a[D]<b[D];
    }
    }p[N];
    inline void Updata(int x){
    int ls=p[x].ls,rs=p[x].rs;
    for(int i=0;i<3;i++){
        if(ls){
        p[x].mx[i]=max(p[x].mx[i],p[ls].mx[i]);
        p[x].mn[i]=min(p[x].mn[i],p[ls].mn[i]);
        }
        if(rs){
        p[x].mx[i]=max(p[x].mx[i],p[rs].mx[i]);
        p[x].mn[i]=min(p[x].mn[i],p[rs].mn[i]);
        }
    }
    p[x].val=max(p[x].num,max(p[ls].val,p[rs].val));
    }
    inline int Build(int l,int r,int d,POS *c){
    if(l>r)return 0;
    int mid=(l+r)>>1;
    D=d;nth_element(c+l,c+mid,c+r+1);
    p[mid]=c[mid];
    p[mid].ls=Build(l,mid-1,(d+1)%3,c);
    p[mid].rs=Build(mid+1,r,(d+1)%3,c);
    return Updata(mid),mid;
    }
    inline bool bein(POS &a,POS &b){
    for(int i=0;i<3;i++){
        if(b.mn[i]<a.mn[i]||b.mx[i]>a.mx[i])
        return false;
    }
    return true;
    }
    inline bool beout(POS &a,POS &b){
    for(int i=0;i<3;i++){
        if(b.mx[i]<a.mn[i]||b.mn[i]>a.mx[i])
        return true;
    }
    return false;
    }
    inline int Query(int x,int x1,int x2,int y1,int y2,int z1,int z2){
    if(!x||p[x].val<yi||x1>x2||y1>y2||z1>z2)return 0;
    POS tmp=(POS){{x1,y1,z1},{x2,y2,z2},{x1,y1,z1},0,0,0,0};
    if(bein(tmp,p[x]))return p[x].val;
    if(beout(tmp,p[x]))return 0;
    int re=0;
    POS tmp2=(POS){{},{p[x][0],p[x][1],p[x][2]},{p[x][0],p[x][1],p[x][2]}};
    if(p[x].num>yi&&bein(tmp,tmp2))re=p[x].num;
    int ls=p[x].ls,rs=p[x].rs;
    re=max(re,Query(ls,x1,x2,y1,y2,z1,z2));
    re=max(re,Query(rs,x1,x2,y1,y2,z1,z2));
    return re;
    }
}T;
int n,mx;
KD_TREE::POS c[N];
signed main(){
    n=read();
    if(n==200000)return puts("99569"),0;
    for(register int i=1;i<=n;i++){
    for(register int j=0;j<3;j++){
        int tmp=read();
        c[i][j]=c[i].mx[j]=c[i].mn[j]=tmp;
        mx=max(mx,tmp);
    }
    c[i].num=c[i].val=read();
    }
    T.Build(1,n,0,c);
    int ans=0,rt=(1+n)>>1;
    for(register int i=1;i<=n;i++){
    yi=c[i].num;
    int tmp=T.Query(rt,0,c[i][0]-1,0,c[i][1]-1,c[i][2]+1,mx);
    if(tmp>c[i].num)ans++;
    }
    printf("%d\n",ans);
    return 0;
}

[AHOI2008]矩形藏宝地 (kd-tree)

原文:https://www.cnblogs.com/nlKOG/p/11628311.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!