[ KD-tree ] BZOJ4358

题解

#include<bits/stdc++.h>
using namespace std;
inline char nc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void Read(int& x){
    char c=nc();
    for(;c<'0'||c>'9';c=nc());
    for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=nc());
}
const int N=50010;
struct Node{
    int vl,vr,mxl,mxr,mnl,mnr;
    int w,ad,co,ha,hc,mx;
    int id,l,r;
}a[N];
int k,n,m,Rt;
int Ans[N],pos[N];
int x;
namespace KDT{
    bool cur;
    inline void Up(int x){
        a[x].co=a[x].hc=-1;
        if(a[x].l){
            a[x].mxl=max(a[x].mxl,a[a[x].l].mxl);
            a[x].mxr=max(a[x].mxr,a[a[x].l].mxr);
            a[x].mnl=min(a[x].mnl,a[a[x].l].mnl);
            a[x].mnr=min(a[x].mnr,a[a[x].l].mnr);
        }
        if(a[x].r){
            a[x].mxl=max(a[x].mxl,a[a[x].r].mxl);
            a[x].mxr=max(a[x].mxr,a[a[x].r].mxr);
            a[x].mnl=min(a[x].mnl,a[a[x].r].mnl);
            a[x].mnr=min(a[x].mnr,a[a[x].r].mnr);
        }
    }
    inline bool Cmp(Node x,Node y){
        return cur?x.vl<y.vl:x.vr<y.vr;
    }
    int Build(int l,int r,bool d){
        int Mid=l+r>>1;
        cur=d;
        nth_element(a+l,a+Mid,a+r+1,Cmp);
        if(l<Mid)a[Mid].l=Build(l,Mid-1,d^1);
        if(r>Mid)a[Mid].r=Build(Mid+1,r,d^1);
        Up(Mid);
        return Mid;
    }
    inline void Down(int x){
        if(a[x].l){
            int y=a[x].l;
            a[y].mx=max(a[y].mx,max(a[x].ha+a[y].w,a[x].hc));
            a[y].hc=max(a[y].hc,a[x].hc);
            if(a[y].co==-1)a[y].ha=max(a[y].ha,a[x].ha+a[y].ad);else a[y].hc=max(a[y].hc,a[x].ha+a[y].co);
            if(a[x].ad){
                a[y].w+=a[x].ad;
                a[y].mx=max(a[y].mx,a[y].w);
                if(a[y].co==-1)a[y].ad+=a[x].ad;else a[y].co+=a[x].ad;
            }
            if(a[x].co!=-1){
                a[y].w=a[y].co=a[x].co;a[y].ad=0;
                a[y].mx=max(a[y].mx,a[y].w);
            }
            a[y].ha=max(a[y].ha,a[y].ad);
            a[y].hc=max(a[y].hc,a[y].co);
        }
        if(a[x].r){
            int y=a[x].r;
            a[y].mx=max(a[y].mx,max(a[x].ha+a[y].w,a[x].hc));
            a[y].hc=max(a[y].hc,a[x].hc);
            if(a[y].co==-1)a[y].ha=max(a[y].ha,a[x].ha+a[y].ad);else a[y].hc=max(a[y].hc,a[x].ha+a[y].co);
            if(a[x].ad){
                a[y].w+=a[x].ad;
                a[y].mx=max(a[y].mx,a[y].w);
                if(a[y].co==-1)a[y].ad+=a[x].ad;else a[y].co+=a[x].ad;
            }
            if(a[x].co!=-1){
                a[y].w=a[y].co=a[x].co;a[y].ad=0;
                a[y].mx=max(a[y].mx,a[y].w);
            }
            a[y].ha=max(a[y].ha,a[y].ad);
            a[y].hc=max(a[y].hc,a[y].co);
        }
        a[x].ad=a[x].ha=0;a[x].co=a[x].hc=-1;
    }
    void Update(int x,int y){
        Down(x);
        if(a[x].mxl<=y&&a[x].mnr>=y){
            a[x].ad++;a[x].ha++;
            a[x].mx=max(a[x].mx,++a[x].w);
            return;
        }
        if(a[x].mnl>y||a[x].mxr<y){
            a[x].co=a[x].hc=a[x].w=0;
            return;
        }
        if(a[x].vl<=y&&y<=a[x].vr)a[x].mx=max(a[x].mx,++a[x].w);else a[x].w=0;
        if(a[x].l)Update(a[x].l,y);
        if(a[x].r)Update(a[x].r,y);
    }
    void Clear(int x){
        Down(x);
        if(a[x].l)Clear(a[x].l);
        if(a[x].r)Clear(a[x].r);
    }
}
int main(){
    Read(n);Read(m);
    for(int i=1;i<=n;i++)Read(x),pos[x]=i;
    for(int i=1;i<=m;i++){
        Read(a[i].vl);Read(a[i].vr);
        a[i].mnl=a[i].mxl=a[i].vl;
        a[i].mnr=a[i].mxr=a[i].vr;
        a[i].id=i;
    }
    Rt=KDT::Build(1,m,0);
    for(int i=1;i<=n;i++)KDT::Update(Rt,pos[i]);
    KDT::Clear(Rt);
    for(int i=1;i<=m;i++)Ans[a[i].id]=a[i].mx;
    for(int i=1;i<=m;i++)printf("%d\n",Ans[i]);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值