BJ模拟:传送门(KD树)

传送门

题解:
注意到这是一个 DAG D A G ,按照拓扑序进行DP。直接上 KD K D 树即可,记得加玄学剪枝。

#include 
using namespace std;
typedef long long LL;
typedef pair <int,int> pii;

const int RLEN=1<<18|1;
inline char nc() {
    static char ibuf[RLEN],*ib,*ob;
    (ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
    char ch=nc(); int i=0,f=1;
    while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
    while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
    return i*f;
}

const int N=2e5+50, INF=0x3f3f3f3f;
int n,ans,nowv;
struct data {
    int x,y,a,b; 
}p[N],st[N];
inline bool cmpx(const data &a,const data &b) {return a.xinline bool cmpy(const data &a,const data &b) {return a.yinline bool cmpx1(int xc1,int yc1,int xc2,int yc2) {return xc1inline bool cmpy1(int xc1,int yc1,int xc2,int yc2) {return yc1inline bool operator == (const data &a,const data &b) {return a.x==b.x && (a.y==b.y);}

struct node {
    node *lc,*rc;
    int mnx,mxx,mny,mxy;
    int mxv,x,y,v;
    inline void upt() {
        mnx=min(x, min(lc->mnx,rc->mnx));
        mny=min(y, min(lc->mny,rc->mny));
        mxx=max(x, max(lc->mxx,rc->mxx));
        mxy=max(y, max(lc->mxy,rc->mxy));
        mxv=max(v, max(lc->mxv,rc->mxv));
    }
}Pool[N],*pool=Pool,*null=Pool,*rt=null;
inline node* newnode(int x,int y) {
    ++pool;
    pool->x=x; pool->y=y;
    pool->mnx=pool->mxx=x;
    pool->mny=pool->mxy=y;
    pool->v=pool->mxv=0;
    pool->lc=null, pool->rc=null;
    return pool;
}

inline void build(node *&x,int l,int r,int d) {
    if(l==r) {x=newnode(st[l].x,st[l].y); return;}
    int mid=(l+r)>>1;
    d ? nth_element(st+l,st+mid,st+r+1,cmpy) : nth_element(st+l,st+mid,st+r+1,cmpx);
    x=newnode(st[mid].x,st[mid].y);
    if(llc,l,mid-1,d^1);
    if(midrc,mid+1,r,d^1);
    x->upt();    
}

inline void modify(node *&now,int x,int y,int v,int d) {
    if(now->x==x && now->y==y) {now->v=max(now->v,v); now->upt(); return;}
    int t=(d ? cmpy1(now->x,now->y,x,y) : cmpx1(now->x,now->y,x,y) );
    t ? modify(now->rc,x,y,v,d^1) : modify(now->lc,x,y,v,d^1);
    now->upt();
}

inline int calc(node *&now,int mnx,int mny,int mxx,int mxy) {
    if(mxxmnx || mnx>now->mxx || mxymny || mny>now->mxy) return -1;
    if(mnx<=now->mnx && mxx>=now->mxx && mny<=now->mny && mxy>=now->mxy) return 0;
    return 1;   
}

inline bool in(node *now,int mnx,int mny,int mxx,int mxy) {
    return now->x>=mnx && now->x<=mxx && now->y>=mny && now->y<=mxy;
}

inline void ask(node *&now,int mnx,int mny,int mxx,int mxy) {
    if(now->mxv<=nowv) return;
    int t=calc(now,mnx,mny,mxx,mxy);
    if(!~t) return;
    if(!t) return (void)(nowv=max(now->mxv,nowv));
    ask(now->lc,mnx,mny,mxx,mxy), ask(now->rc,mnx,mny,mxx,mxy);
    if(now->v>nowv && in(now,mnx,mny,mxx,mxy)) nowv=max(nowv,now->v);
}

int main() {
    n=rd();
    null->mnx=pool->mny=INF;
    null->mxx=pool->mxy=-INF;
    for(int i=1;i<=n;i++) 
        p[i].x=rd(), p[i].y=rd(), p[i].a=rd(), p[i].b=rd(), st[i]=p[i];
    sort(st+1,st+n+1,cmpx);
    int tot=unique(st+1,st+n+1)-st-1;
    build(rt,1,tot,0);
    sort(p+1,p+n+1,cmpx);
    for(int i=n;i;i--) {
        nowv=0;
        ask(rt,p[i].x,p[i].y,p[i].a,p[i].b);
        ans=max(ans,nowv+1);
        modify(rt,p[i].x,p[i].y,nowv+1,0);
    }
    cout<

你可能感兴趣的:(k-d树)