BZOJ 4066: 简单题【替罪羊树重构K-D Tree】

题目链接


   题的名称叫做“简单题”,实际上不简单——题记

  没有任何的花里胡哨,卡了空间!!!

  也就是说,只能用数据结构来维护咯,舍弃时间也不能浪费空间啊,多一丢丢都会MLE。

  所以,就变成动态开点平衡二叉树操作吧,但是真的平衡嘛?KD Tree建树的话,跟输入有关,还真不平衡?怎么维护其平衡呢?那么就是替罪羊树不断的重构不平衡的二叉树吧,这里不能添加判断平衡的数组了,因为空间实在不管够啊,于是,直接每插入5000个点,就重构一下!

  查询?查询当然暴力查啊,因为尽可能让它是一棵平衡二叉树,所以暴力查的话,基本上维持在log()左右。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
//#include <unordered_map>
//#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define eps 1e-8
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define MP(a, b) make_pair(a, b)
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int K = 2, maxN = 2e5 + 7;
int N, root = 0, ch[maxN][2] = {0}, key[maxN], pp, tot = 0;
struct node
{
    int d[K], val;
    node(int a=0, int b=0, int c=0):d{a, b}, val(c) {}
    friend bool operator < (node e1, node e2) { return e1.d[pp] < e2.d[pp]; }
} tree[maxN], p;
int mn[maxN][2], mx[maxN][2], sum[maxN] = {0};
inline void pushup(int rt)
{
    for(int i=0; i<K; i++)
    {
        if(ch[rt][0] && ch[rt][1])
        {
            mn[rt][i] = min(tree[rt].d[i], min(mn[ch[rt][0]][i], mn[ch[rt][1]][i]));
            mx[rt][i] = max(tree[rt].d[i], max(mx[ch[rt][0]][i], mx[ch[rt][1]][i]));
        }
        else if(ch[rt][0])
        {
            mn[rt][i] = min(tree[rt].d[i], mn[ch[rt][0]][i]);
            mx[rt][i] = max(tree[rt].d[i], mx[ch[rt][0]][i]);
        }
        else if(ch[rt][1])
        {
            mn[rt][i] = min(tree[rt].d[i], mn[ch[rt][1]][i]);
            mx[rt][i] = max(tree[rt].d[i], mx[ch[rt][1]][i]);
        }
        else mn[rt][i] = mx[rt][i] = tree[rt].d[i];
    }
    sum[rt] = sum[ch[rt][0]] + sum[ch[rt][1]] + tree[rt].val;
}
int build(int l, int r, int fa)
{
    if(l > r) return 0;
    int mid = HalF;
    pp = key[fa] ^ 1;
    key[mid] = pp;
    nth_element(tree + l, tree + mid, tree + r + 1);
    ch[mid][0] = build(l, mid - 1, mid);
    ch[mid][1] = build(mid + 1, r, mid);
    pushup(mid);
    return mid;
}
void Insert(int &rt, int fa, int val)
{
    pp = key[fa] ^ 1;
    if(!rt)
    {
        rt = ++tot;
        tree[rt] = p;
        key[rt] = pp;
    }
    else Insert(ch[rt][tree[rt] < p], rt, val);
    pushup(rt);
}
int x_1, y_1, x_2, y_2;
int query(int rt)
{
    if(!rt) return 0;
    if(mn[rt][0] > x_2 || mx[rt][0] < x_1 || mn[rt][1] > y_2 || mx[rt][1] < y_1) return 0;
    int ans = 0;
    if(mn[rt][0] >= x_1 && mx[rt][0] <= x_2 && mn[rt][1] >= y_1 && mx[rt][1] <= y_2) return sum[rt];
    if(tree[rt].d[0] >= x_1 && tree[rt].d[0] <= x_2 && tree[rt].d[1] >= y_1 && tree[rt].d[1] <= y_2) ans += tree[rt].val;
    ans += query(ch[rt][0]);
    ans += query(ch[rt][1]);
    return ans;
}
int main()
{
    scanf("%d", &N);
    int op, vv, ans = 0;
    key[0] = 0;
    while(scanf("%d", &op) && (op ^ 3))
    {
        if(op == 1)
        {
            scanf("%d%d%d", &x_1, &y_1, &vv); x_1 ^= ans; y_1 ^= ans; vv ^= ans;
            p = node(x_1, y_1, vv);
            Insert(root, 0, vv);
            if(tot % 5000 == 0) root = build(1, tot, 0);
        }
        else
        {
            scanf("%d%d%d%d", &x_1, &y_1, &x_2, &y_2); x_1 ^= ans; y_1 ^= ans; x_2 ^= ans; y_2 ^= ans;
            ans = query(root);
            printf("%d\n", ans);
        }
    }
    return 0;
}
/*
4
1 2 3 3
2 1 1 3 3
1 1 1 1
2 1 1 0 7
3
*/
发布了884 篇原创文章 · 获赞 1057 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/qq_41730082/article/details/105185964