簡單題(K-D Tree+單點插入+矩形區間和)

簡單題

不知道爲什麼取這個名字QAQ,有個地方初始化不對,在洛谷上掛了一頁。

題意:在這裏插入圖片描述
特點: 強制在線(last_ans)+20M內存限制

思路: 沒啥思路,就是K-D Tree板子題,因此下面記錄K-D Tree的一些信息

  1. K-D Tree也算二叉+平衡+樹吧?用於維護K-Dimension的信息,將K維空間不斷地通過某一維度的中位數點進行當前空間的分割。
  2. 特點:樹的節點數跟空間中點數相同(動態開點+節點回收),平衡時高度爲[log2n][log_2n]
  3. 一些需要維護的基礎信息:
    1. lsonrson:lson,rson:當前節點左兒子+右兒子
    2. sum:sum:當前子樹的所有節點權值和(也可能是其他區間信息)
    3. size:size:當前子樹節點總數
    4. point:point:當前節點所代表的空間中的一個點
    5. mi[i]:mi[i]:當前子樹空間中第ii維的下界
    6. mx[i]:mx[i]:當前子樹空間中第ii維的上界
  4. 一些常用基礎函數:
    1. nth_element(tp+l,tp+m,tp+r+1); 用於log2nlog_2n時間複雜度選出中點且將數組分成兩邊
    2. void rebuild(int l, int r, int dim, int &now);重構時調用的建樹
    3. void to_array(int idx, int now);重構前將當前子樹轉化爲數組並存在某臨時數組中
    4. void check(int dim, int &now);檢查當前子樹是否相對平衡
    5. void insert(P np, int dim, int &now);插入一個新的點

代碼

#include "bits/stdc++.h"
#define hhh printf("hhh\n")
#define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
using namespace std;
inline int read() {int x=0,f=1;char c=getchar();while(c!='-'&&(c<'0'||c>'9'))c=getchar();if(c=='-')f=-1,c=getchar();while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();return f*x;}

const int maxn = 2e5+10;

struct P{ int x[2], w; }p[maxn], tp[maxn];
int ls[maxn], rs[maxn], sum[maxn], sz[maxn];
int mi[maxn][2], mx[maxn][2];
int rub[maxn], top, tot, Dim, rt;
int N, last_ans;

bool operator < (P a, P b) { return a.x[Dim]<b.x[Dim]; }

inline void Min(int &x, int y) { if(x>y) x=y; }
inline void Max(int &x, int y) { if(x<y) x=y; }

int newnode() {
    if(top) return rub[top--];
    return ++tot;
}

void push_up(int now) {
    for(int i=0; i<2; ++i) {
        mi[now][i]=mx[now][i]=p[now].x[i];
        if(ls[now]) Min(mi[now][i],mi[ls[now]][i]), Max(mx[now][i],mx[ls[now]][i]);
        if(rs[now]) Min(mi[now][i],mi[rs[now]][i]), Max(mx[now][i],mx[rs[now]][i]);
    }
    sum[now]=sum[ls[now]]+sum[rs[now]]+p[now].w;
    sz[now]=sz[ls[now]]+sz[rs[now]]+1;
}

void rebuild(int l, int r, int dim, int &now) {
    if(l>r) { now=0; return; } //千萬別忘了now=0!!!
    now=newnode();
    int m=(l+r)/2;
    Dim=dim; nth_element(tp+l,tp+m,tp+r+1); p[now]=tp[m];
    rebuild(l,m-1,dim^1,ls[now]); rebuild(m+1,r,dim^1,rs[now]);
    push_up(now);
}

void to_array(int idx, int now) {
    if(ls[now]) to_array(idx,ls[now]);
    tp[idx+sz[ls[now]]]=p[now]; rub[++top]=now;
    if(rs[now]) to_array(idx+sz[ls[now]]+1,rs[now]);
}

void check(int dim, int &now) {
    if(sz[now]*3<sz[ls[now]]*4||sz[now]*3<sz[rs[now]]*4) {
        to_array(1,now); rebuild(1,sz[now],dim,now);
    }
}

void insert(P np, int dim, int &now) {
    if(!now) {
        now=newnode(), ls[now]=rs[now]=0;
        p[now]=np;
        push_up(now);
        return;
    }
    if(np.x[dim]<=p[now].x[dim]) insert(np,dim^1,ls[now]);
    else insert(np,dim^1,rs[now]);
    push_up(now); check(dim,now);
}

inline bool in(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) {
    return x1>=x3&&y1>=y3&&x2<=x4&&y2<=y4;
}
inline bool out(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) {
    return x1>x4||x2<x3||y1>y4||y2<y3;
}

int query(int x1, int y1, int x2, int y2, int now) {
    if(!now) return 0;
    if(out(mi[now][0],mi[now][1],mx[now][0],mx[now][1],x1,y1,x2,y2)) return 0;
    if(in(mi[now][0],mi[now][1],mx[now][0],mx[now][1],x1,y1,x2,y2)) return sum[now];
    if(in(p[now].x[0],p[now].x[1],p[now].x[0],p[now].x[1],x1,y1,x2,y2))
        return p[now].w+query(x1,y1,x2,y2,ls[now])+query(x1,y1,x2,y2,rs[now]);
    return query(x1,y1,x2,y2,ls[now])+query(x1,y1,x2,y2,rs[now]);
}

int main() {
    N=read();
    int op;
    while(scanf("%d", &op), op!=3) {
        if(op==1) {
            int x=read()^last_ans, y=read()^last_ans, A=read()^last_ans;
            insert((P){x,y,A},0,rt);
        }
        else {
            int x1=read()^last_ans, y1=read()^last_ans, x2=read()^last_ans, y2=read()^last_ans;
            printf("%d\n", last_ans=query(x1,y1,x2,y2,rt));
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章