2018牛客多校6 - I Team Rocket KD树维护空间

题意:给出n条铁路区间\([L,R]\),共有m个boom依时间顺序放置在\(k_i\)中,区间与\(k_i\)有交集的都被炸掉

求每次炸掉的铁路个数和最后输出所有id被炸的时间点

炸弹能炸到的区间满足\(L≤K≤R\)

因为\(L\)\(R\)无关,将其关系改写为\(X≤K≤Y\),

对应于二维空间,铁路区间相当于一个点\((L,R)\),每次询问有多少个没被屏蔽的点满足\(X≤K\)\(K≤Y\)

然后KD树乱搞剪枝就好

唯一的问题是屏蔽掉的点无法在push_up时再次更新两个维度的极左极右值\(lx,rx\)(要么再多维护次左次右值)

幸好没被卡(反而跑的贼快

#include<bits/stdc++.h>
#define rep(i,j,k) for(register int i=j;i<=k;i++)
#define rrep(i,j,k) for(register int i=j;i>=k;i--)
#define erep(i,u) for(register int i=head[u];~i;i=nxt[i])
#define print(a) printf("%lld",(ll)a)
#define println(a) printf("%lld\n",(ll)a)
#define printbk(a) printf("%lld ",(ll)a)
#define IOS ios::sync_with_stdio(0)
using namespace std;
const int MAXN = 3e5+11;
const int INF = 0x3f3f3f3f;
const double EPS = 1e-7;
typedef long long ll;
const ll MOD = 998244353;
ll read(){
    ll x=0,f=1;register char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int D,CLOCK;
int ans[MAXN];
ll sum,prod;
struct POINT{
    int x[2],idx;
    bool operator < (const POINT &rhs) const{
        return x[D]<rhs.x[D];
    }
}p[MAXN];
struct KD{
    int lx[MAXN][2],rx[MAXN][2];
    int son[MAXN][2],size[MAXN];
    int mark[MAXN];
    int root;
    #define lc son[o][0]
    #define rc son[o][1]
    void pu(int o){
        size[o]=mark[o];
        if(lc) size[o]+=size[lc];
        if(rc) size[o]+=size[rc];
        rep(i,0,1){
            if(lc&&lx[lc][i]<lx[o][i]) lx[o][i]=lx[lc][i];
            if(rc&&lx[rc][i]<lx[o][i]) lx[o][i]=lx[rc][i];
            if(lc&&rx[lc][i]>rx[o][i]) rx[o][i]=rx[lc][i];
            if(rc&&rx[rc][i]>rx[o][i]) rx[o][i]=rx[rc][i]; 
        }
    }
    int build(int d,int l,int r){
        int mid=l+r>>1; D=d; mark[mid]=1;
        nth_element(p+l,p+mid,p+r+1);
        rep(i,0,1) lx[mid][i]=rx[mid][i]=p[mid].x[i];
        size[mid]=1;son[mid][0]=son[mid][1]=0;
        if(l<mid) son[mid][0]=build(d^1,l,mid-1);
        if(r>mid) son[mid][1]=build(d^1,mid+1,r);
        pu(mid);
        return mid;
    }
    void query(int o,int k){
        if(!o) return;
        if(!size[o]) return;
        if(lx[o][0]>k||rx[o][1]<k) return;
        if(mark[o]&&p[o].x[0]<=k&&p[o].x[1]>=k){
            ans[p[o].idx]=CLOCK;
            sum++; prod=(prod*p[o].idx)%MOD;
            mark[o]=0;
        }
        if(lc) query(lc,k);
        if(rc) query(rc,k);
        pu(o);
    }
}kd;
int main(){
    int T=read(),kase=0,n,m;
    while(T--){
        n=read(); m=read();
        rep(i,1,n){
            p[i].x[0]=read();
            p[i].x[1]=read();
            p[i].idx=i;
        }
        memset(ans,0,sizeof ans);
        //kd.baoli();
        kd.root=kd.build(0,1,n);
        ll lastans=0; CLOCK=0;
        printf("Case #%d:\n",++kase);
        while(m--){
            sum=0; prod=1;
            ll pos=lastans^read();
            ++CLOCK;
            kd.query(kd.root,pos);
            println(sum);
            if(sum) lastans=prod;
            else lastans=0;
        }
        rep(i,1,n){
            if(i==n) println(ans[i]);
            else printbk(ans[i]);
        }
    }
    return 0;
}
posted @ 2018-08-05 12:30  Caturra  阅读(233)  评论(0编辑  收藏  举报