bzoj4605 崂山白花蛇草水(动态开点线段树逃替罪羊重构K-D tree)

首先我们发现它是一个三维的问题而且还强制在线 囧
我们可以考虑在外面来一个权值线段树,然后每次查询时在线段树二分即可,这样我们每个节点再套一棵K-D tree,用来查询有多少个点被框住了,然后因为是不断往里插点,所以还要替罪羊式重构维护一下K-D tree。
最后复杂度就是 O(qlogwn) O ( q l o g w n )

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 500010
#define alpha 0.77
inline char gc(){
    static char buf[1<<16],*S,*T;
    if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
    return *S++;
}
inline int read(){
    int x=0,f=1;char ch=gc();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=gc();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
    return x*f;
}
int n,m,rt[N*6],D,Rt=0,owo=0,lc[N*6],rc[N*6],ofo=0,tot,lastans=0;
int *pp,ppop;
struct point{
    int d[2],id;
    int& operator[](int x){return d[x];}
    friend bool operator<(point a,point b){return a[D]<b[D];}
}t1,t2,a[N];
struct node{
    point x;int lc,rc,mx[2],mn[2],sz;
}tr[N*6];
inline void update(int p){
    int l=tr[p].lc,r=tr[p].rc;
    for(int i=0;i<2;++i){
        tr[p].mx[i]=max(tr[p].x[i],max(tr[l].mx[i],tr[r].mx[i]));
        tr[p].mn[i]=min(tr[p].x[i],min(tr[l].mn[i],tr[r].mn[i]));
    }tr[p].sz=tr[l].sz+tr[r].sz+1;
}
inline void ins(int &p,int op){
    if(!p){p=++ofo;tr[p].x=t1;update(p);return;}D=op;
    if(t1<tr[p].x) ins(tr[p].lc,op^1);
    else ins(tr[p].rc,op^1);update(p);
    if(max(tr[tr[p].lc].sz,tr[tr[p].rc].sz)>tr[p].sz*alpha) pp=&p,ppop=op;
}
void dfs(int p){
    a[++tot]=tr[p].x;a[tot].id=p;
    if(tr[p].lc) dfs(tr[p].lc);
    if(tr[p].rc) dfs(tr[p].rc);tr[p].lc=tr[p].rc=0;
}
inline void build(int &p,int l,int r,int op){
    D=op;int mid=l+r>>1;nth_element(a+l,a+mid,a+r+1);
    p=a[mid].id;tr[p].x=a[mid];
    if(l<mid) build(tr[p].lc,l,mid-1,op^1);
    if(r>mid) build(tr[p].rc,mid+1,r,op^1);update(p);
}
inline void seg_ins(int &p,int l,int r,int x){
    if(!p) p=++owo;pp=NULL;ins(rt[p],0);
    if(pp) tot=0,dfs(*pp),build(*pp,1,tot,ppop);
    if(l==r) return;int mid=l+r>>1;
    if(x<=mid) seg_ins(lc[p],l,mid,x);
    else seg_ins(rc[p],mid+1,r,x);
}
inline bool in(int p){
    return t1[0]<=tr[p].mn[0]&&t1[1]<=tr[p].mn[1]&&t2[0]>=tr[p].mx[0]&&t2[1]>=tr[p].mx[1];
}
inline bool out(int p){
    return tr[p].mx[0]<t1[0]||tr[p].mx[1]<t1[1]||tr[p].mn[0]>t2[0]||tr[p].mn[1]>t2[1];
}
inline bool inn(point x){
    return t1[0]<=x[0]&&t1[1]<=x[1]&&t2[0]>=x[0]&&t2[1]>=x[1];
}
inline int ask(int p){
    if(!p) return 0;
    if(in(p)) return tr[p].sz;
    if(out(p)) return 0;
    return inn(tr[p].x)+ask(tr[p].lc)+ask(tr[p].rc);
}
inline int query(int p,int l,int r,int k){
    if(l==r) return l;int mid=l+r>>1,res=ask(rt[rc[p]]);
    if(res>=k) return query(rc[p],mid+1,r,k);
    return query(lc[p],l,mid,k-res);
}
int main(){
//  freopen("a.in","r",stdin);
    n=read();m=read();
    for(int i=0;i<2;++i) tr[0].mx[i]=0,tr[0].mn[i]=inf;
    while(m--){
        int op=read();t1[0]=read()^lastans,t1[1]=read()^lastans;
        if(op==1) seg_ins(Rt,1,1e9,read()^lastans);
        else{
            t2[0]=read()^lastans,t2[1]=read()^lastans;int k=read()^lastans;
            if(ask(rt[1])<k){puts("NAIVE!ORZzyz.");lastans=0;}
            else printf("%d\n",lastans=query(Rt,1,1e9,k));
        }
    }return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值