BZOJ 4066 - KDtree + 重构

版权声明:欢迎随便转载。 https://blog.csdn.net/a1214034447/article/details/82931452

题目链接:点击这里

解题思路:

这题被强制在线了如果是离线(BZOJ 2683)可以CDQ分治 + 树状数组做.

所以只能用KDtree了.

若每次都将新节点插入原DKT中,最终会导致树会非常的不平衡,而失去了意义,导致超时.

所以我们要设置一个阈值,当节点数到达阈值时就对KDT进行重构保证稳定.

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define inf 0x3f3f3f3f
#define fi first
#define se second
using namespace std;
const int mx = 2e5 + 10;
const int mod = 1<<30;
typedef long long ll;
int n,m,now;
int x1,x2,y1,y2,z;
struct node
{
    int mi[2],ma[2];
    int l,r,d[2],siz,sum;
    bool operator < (node A)const
    {
        return d[now] < A.d[now];
    }
}s[mx];
void update(int rt,int to)
{
    for(int i=0;i<2;i++){
        s[rt].mi[i] = min(s[rt].mi[i],s[to].mi[i]);
        s[rt].ma[i] = max(s[rt].ma[i],s[to].ma[i]);
    }
    s[rt].sum += s[to].sum;
}
int build(int l,int r,int rt)
{
    int mid = (l+r)>>1;
    now = rt;
    nth_element(s+l,s+mid,s+r+1);
    s[mid].sum = s[mid].siz;
    for(int i=0;i<2;i++) s[mid].mi[i] = s[mid].ma[i] = s[mid].d[i];
    if(l!=mid) s[mid].l = build(l,mid-1,rt^1); else s[mid].l = 0;
    if(r!=mid) s[mid].r = build(mid+1,r,rt^1); else s[mid].r = 0;
    if(l!=mid) update(mid,s[mid].l);
    if(r!=mid) update(mid,s[mid].r);
    return mid;
}
void insert(int rt,int p)
{
    now = 0;
    while(1){
        update(rt,p);
        if(s[rt].d[now]>s[p].d[now])
        {
            if(!s[rt].l){
                s[rt].l = p;
                return;
            }
            rt = s[rt].l;
        }else{
            if(!s[rt].r){
                s[rt].r = p;
                return ;
            }
            rt = s[rt].r;
        }
        now ^= 1;
    }
}
bool in(int x,int y)
{
    if(x>=x1&&x<=x2&&y>=y1&&y<=y2) return 1;
    return 0;
}
int judge(int rt)
{
    bool f1 = in(s[rt].mi[0],s[rt].mi[1]);
    bool f2 = in(s[rt].ma[0],s[rt].ma[1]);
    if(f1&&f2) return 1;
    if(max(x1,s[rt].mi[0])>min(x2,s[rt].ma[0])) return -1;
    if(max(y1,s[rt].mi[1])>min(y2,s[rt].ma[1])) return -1;
    return 0;
}
int query(int rt)
{
    int st = judge(rt);
    if(st==-1) return 0;
    if(st==1) return s[rt].sum;
    if(in(s[rt].d[0],s[rt].d[1])) st = s[rt].siz;
    return st + query(s[rt].l) + query(s[rt].r);
}
int main()
{
    scanf("%d",&n);
    int ans = 0,cnt = 0;
    int root = 1,up = 10000;
    while(scanf("%d",&z)&&z!=3)
    {
        if(z==1){
            scanf("%d%d%d",&x1,&y1,&x2);
            s[++cnt].d[0] = x1^ans;
            s[cnt].d[1] = y1^ans;
            s[cnt].sum = s[cnt].siz = x2^ans;
            for(int i=0;i<2;i++) s[cnt].mi[i] = s[cnt].ma[i] = s[cnt].d[i];
            if(cnt==up){
                up += 10000;
                root = build(1,cnt,0);
            }else if(cnt!=1) insert(root,cnt);
        }else{
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            x1 ^= ans,y1 ^= ans,x2 ^= ans,y2 ^= ans;
            if(x1>x2) swap(x1,x2);
            if(y1>y2) swap(y1,y2);
            ans = query(root);
            printf("%d\n",ans);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/a1214034447/article/details/82931452
今日推荐