HDU 5126 stars KDTree

stars



Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 980    Accepted Submission(s): 311


Problem Description
John loves to see the sky. A day has Q times. Each time John will find a new star in the sky, or he wants to know how many stars between  (x1,y1,z1)  and  (x2,y2,z2) .
 

Input
The first line contains a single integer  T(1T10)  (the data for  Q>100  less than 6 cases),, indicating the number of test cases.
The first line contains an integer  Q(1Q50000) ,indicating how many times in a day.
Next Q lines contain some integers, first input an integer  A(1A2) .If A=1 then input 3 integers x, y and z, indicating a coordinate of one star.. If A=2 then input 6 integers  x1,y1,z1,x2,y2,z2(1x,y,z,x1,y1,z1,x2,y2,z2109,x1x2,y1y2,z1z2) .
 

Output
For each “A=2”,output an integer means how many stars in such a section.
 

Sample Input
  
  
2 11 1 1 1 1 2 1 1 1 1 1 1 1 2 2 2 1 1 1 2 2 1 1 1 2 2 2 1 3 3 3 1 4 4 4 1 5 5 5 1 6 6 6 2 1 1 1 6 6 6 2 3 3 3 6 6 6 11 1 1 1 1 2 1 1 1 1 1 1 1 2 2 2 1 1 1 2 2 1 1 1 2 2 2 1 3 3 3 1 4 4 4 1 5 5 5 1 6 6 6 2 1 1 1 6 6 6 2 3 3 3 6 6 6
 

Sample Output
  
  
1 3 7 4 1 3 7 4
 
KD树裸题,最开始想着先不重构KD树,交上去试试,如果超时了再改。结果一直WA,一直在找BUG都找不到,实在没办法就试着重构KD树,于是就每1000个节点重构一次KD树,直接A了,没想到明明超时OJ却判成WA。

#include <bits/stdc++.h>
#define maxn 100010
#define inf 0x7fffffff
using namespace std;
int n, m, root, cmpd;
struct data
{
    int l, r, d[3], mx[3], mn[3], sum, w; // sum:以此为根节点数目和  w:节点上数字
    data() {}
    data(int a, int b, int c, int val)
    {
        l = r = 0;
        d[0] = mx[0] = mn[0] = a;
        d[1] = mx[1] = mn[1] = b;
        d[2] = mx[2] = mn[2] = c;
        w = sum = val;
    }
} tr[maxn];
void update(int x)
{
    int l = tr[x].l, r = tr[x].r;
    if (l) // 维护以此为根的子树各个维度范围与节点数目和
    {
        tr[x].mx[0] = max(tr[x].mx[0], tr[l].mx[0]);
        tr[x].mn[0] = min(tr[x].mn[0], tr[l].mn[0]);
        tr[x].mx[1] = max(tr[x].mx[1], tr[l].mx[1]);
        tr[x].mn[1] = min(tr[x].mn[1], tr[l].mn[1]);
        tr[x].mx[2] = max(tr[x].mx[2], tr[l].mx[2]);
        tr[x].mn[2] = min(tr[x].mn[2], tr[l].mn[2]);
        tr[x].sum += tr[l].sum;
    }
    if (r)
    {
        tr[x].mx[0] = max(tr[x].mx[0], tr[r].mx[0]);
        tr[x].mn[0] = min(tr[x].mn[0], tr[r].mn[0]);
        tr[x].mx[1] = max(tr[x].mx[1], tr[r].mx[1]);
        tr[x].mn[1] = min(tr[x].mn[1], tr[r].mn[1]);
        tr[x].mx[2] = max(tr[x].mx[2], tr[r].mx[2]);
        tr[x].mn[2] = min(tr[x].mn[2], tr[r].mn[2]);
        tr[x].sum += tr[r].sum;
    }
}
int cmp(data a, data b)
{
    if (a.d[cmpd] == b.d[cmpd])
    {
        if (a.d[(cmpd + 1) % 3] == b.d[(cmpd + 1) % 3])
        {
            return a.d[(cmpd + 2) % 3] < b.d[(cmpd + 2) % 3];
        }
        return a.d[(cmpd + 1) % 3] < b.d[(cmpd + 1) % 3];
    }
    return a.d[cmpd] < b.d[cmpd];
}
int build(int l, int r, int d)
{
    int mid = (l + r) >> 1;
    cmpd = d;
    //不对整体排序,只求第n小的元素并放在其位置上
    nth_element(tr + l, tr + mid, tr + r + 1, cmp);
    tr[mid].mx[0] = tr[mid].mn[0] = tr[mid].d[0];
    tr[mid].mx[1] = tr[mid].mn[1] = tr[mid].d[1];
    tr[mid].mx[2] = tr[mid].mn[2] = tr[mid].d[2];
    tr[mid].sum = tr[mid].w;
    tr[mid].l = 0;
    tr[mid].r = 0;
    if (l < mid)
    {
        tr[mid].l = build(l, mid - 1, (d + 1) % 3);
    }
    if (r > mid)
    {
        tr[mid].r = build(mid + 1, r, (d + 1) % 3);
    }
    update(mid);
    return mid;
}
void kdinsert(int now)
{
    if (now == root)
    {
        return;
    }
    int D, p;
    D = 0;
    p = root;
    while (true)
    {
        //插入到P中,维护信息
        if (tr[now].mx[0] > tr[p].mx[0])
        {
            tr[p].mx[0] = tr[now].mx[0];
        }
        if (tr[now].mx[1] > tr[p].mx[1])
        {
            tr[p].mx[1] = tr[now].mx[1];
        }
        if (tr[now].mx[2] > tr[p].mx[2])
        {
            tr[p].mx[2] = tr[now].mx[2];
        }
        if (tr[now].mn[0] < tr[p].mn[0])
        {
            tr[p].mn[0] = tr[now].mn[0];
        }
        if (tr[now].mn[1] < tr[p].mn[1])
        {
            tr[p].mn[1] = tr[now].mn[1];
        }
        if (tr[now].mn[2] < tr[p].mn[2])
        {
            tr[p].mn[2] = tr[now].mn[2];
        }
        tr[p].sum += tr[now].sum;
        if (tr[p].d[0] == tr[now].d[0] && tr[p].d[1] == tr[now].d[1] && tr[p].d[2] == tr[now].d[2]) //相等时只更新不插入
        {
            tr[p].w += tr[now].w;
            m--;
            return;
        }
        if (tr[now].d[D] >= tr[p].d[D])
        {
            if (tr[p].r == 0)
            {
                tr[p].r = now;
                return;
            }
            else
            {
                p = tr[p].r;
            }
        }
        else
        {
            if (tr[p].l == 0)
            {
                tr[p].l = now;
                return;
            }
            else
            {
                p = tr[p].l;
            }
        }
        D = (D + 1) % 3;
    }
}
int query(int now, int x1, int y1, int z1, int x2, int y2, int z2)
{
    // 当前节点范围与查询矩形不相交
    if (!now || tr[now].mx[0] < x1 || tr[now].mn[0] > x2 || tr[now].mx[1] < y1 || tr[now].mn[1] > y2 || tr[now].mx[2] < z1 || tr[now].mn[2] > z2)
    {
        return 0;
    }
    // 当前节点范围包含查询矩形
    if (tr[now].mx[0] <= x2 && tr[now].mn[0] >= x1 && tr[now].mx[1] <= y2 && tr[now].mn[1] >= y1 && tr[now].mx[2] <= z2 && tr[now].mn[2] >= z1)
    {
        return tr[now].sum;
    }
    int ret = 0;
    // 查询矩形包含当前节点
    if (tr[now].d[0] >= x1 && tr[now].d[0] <= x2 && tr[now].d[1] >= y1 && tr[now].d[1] <= y2 && tr[now].d[2] >= z1 && tr[now].d[2] <= z2)
    {
        ret += tr[now].w;
    }
    ret += query(tr[now].l, x1, y1, z1, x2, y2, z2) + query(tr[now].r, x1, y1, z1, x2, y2, z2);
    return ret;
}
int main()
{
#ifdef LOCAL
    freopen("data.in", "r", stdin);
    freopen("data.out", "w", stdout);
#endif
    int t;
    scanf("%d", &t);
    while (t--)
    {
        scanf("%d", &n);
        int op;
        m = 0;
        int mod = 10000;
        root = 1;
        while (n--)
        {
            scanf("%d", &op);
            if (op == 1)
            {
                int x, y, z;
                scanf("%d %d %d", &x, &y, &z);
                tr[++m] = data(x, y, z, 1);
                kdinsert(m);
                if (m % mod == 0) //每mod次重建KD树
                {
                    root = build(1, m, 0);
                }
            }
            else
            {
                int x1, y1, z1, x2, y2, z2;
                scanf("%d %d %d %d %d %d", &x1, &y1, &z1, &x2, &y2, &z2);
                int ans = query(root, x1, y1, z1, x2, y2, z2);
                printf("%d\n", ans);
            }
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值