• bzoj4066


    KD-tree

    强制在线就不能愉快的做这道题了。

    我们用KD-tree维护平面上的点,这样建出来的树高大概是log,复杂度过得去,但是插入过多会使树深很深,这样就能卡死,那么我们每个10000次插入就重构一次。

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 2e5 + 5;
    int n, root, cnt, m = 10000, d, last;
    struct data {
        int x, y, mx_x, mn_x, mx_y, mn_y, lc, rc, sum, val;
        bool friend operator < (const data &a, const data &b) {
            if(d == 0) return a.x == b.x ? a.y < b.y : a.x < b.x;
            if(d == 1) return a.y == b.y ? a.x < b.x : a.y < b.y;
        }
        bool friend operator == (const data &a, const data &b) {
            return a.x == b.x && a.y == b.y;
        }
    } a[N], b[N];
    inline void read(int &x)
    {
        x = 0;
        int f = 1; char c = getchar();
        while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); }
        while(c >= '0' && c <= '9') { x = (x << 1) + (x << 3) + c - '0'; c = getchar(); }
        x *= f;
    }
    bool in(int x1, int y1, int x2, int y2, int X1, int Y1, int X2, int Y2)
    {
        return X1 >= x1 && Y1 >= y1 && x2 >= X2 && y2 >= Y2;
    }
    bool out(int x1, int y1, int x2, int y2, int X1, int Y1, int X2, int Y2)
    {
        return x1 > X2 || x2 < X1 || y1 > Y2 || y2 < Y1;
    }
    void update(int x)
    {
        a[x].mn_x = min(a[x].x, min(a[a[x].lc].mn_x, a[a[x].rc].mn_x));
        a[x].mx_x = max(a[x].x, max(a[a[x].lc].mx_x, a[a[x].rc].mx_x));
        a[x].mn_y = min(a[x].y, min(a[a[x].lc].mn_y, a[a[x].rc].mn_y));
        a[x].mx_y = max(a[x].y, max(a[a[x].lc].mx_y, a[a[x].rc].mx_y));
        a[x].sum = a[x].val + a[a[x].lc].sum + a[a[x].rc].sum; 
    }  
    int build(int l, int r, int D)
    {
        if(l > r) return 0;
        d = D;
        int mid = (l + r) >> 1;
        nth_element(b + l, b + mid, b + r + 1);
        a[mid] = b[mid];
        a[mid].lc = build(l, mid - 1, D ^ 1);
        a[mid].rc = build(mid + 1, r, D ^ 1);
        update(mid);
        return mid;
    }
    void insert(int &x, const data &tmp, int D)
    {
        d = D;
        if(!x) 
        {
            x = ++cnt;
            a[x].x = a[x].mn_x = a[x].mx_x = tmp.x;
            a[x].y = a[x].mn_y = a[x].mx_y = tmp.y;
            a[x].sum = a[x].val = tmp.val;
            return;
        }
        if(a[x] == tmp) 
        {
            a[x].val += tmp.val;
            a[x].sum += tmp.val;
            return;
        }
        if(tmp < a[x]) insert(a[x].lc, tmp, D ^ 1);
        else insert(a[x].rc, tmp, D ^ 1);
        update(x);
    }
    int query(int x, int x1, int y1, int x2, int y2)
    {
        if(!x) return 0;
        int ret = 0;
        if(in(x1, y1, x2, y2, a[x].mn_x, a[x].mn_y, a[x].mx_x, a[x].mx_y)) return a[x].sum; 
        if(out(x1, y1, x2, y2, a[x].mn_x, a[x].mn_y, a[x].mx_x, a[x].mx_y)) return 0;
        if(in(x1, y1, x2, y2, a[x].x, a[x].y, a[x].x, a[x].y)) ret += a[x].val;
        ret += query(a[x].lc, x1, y1, x2, y2) + query(a[x].rc, x1, y1, x2, y2);
        return ret;
    }
    int main()
    {
    //  freopen("bzoj_4066.in", "r", stdin);
    //  freopen("bzoj_4066.out", "w", stdout);
        a[0].mn_x = 1e9;
        a[0].mx_x = -1e9;
        a[0].mn_y = 1e9;
        a[0].mx_y = -1e9;
        b[0].mn_x = 1e9;
        b[0].mx_x = -1e9;
        b[0].mn_y = 1e9;
        b[0].mx_y = -1e9;
        read(n);
        while(1)
        {
            int opt, x1, y1, x2, y2;
            data tmp;
            read(opt);
            if(opt == 1) 
            {
                read(tmp.x);
                read(tmp.y);
                read(tmp.val);
                tmp.x ^= last;
                tmp.y ^= last;
                tmp.val ^= last;
                insert(root, tmp, 0);
                if(cnt == m)
                {
                    for(int i = 1; i <= cnt; ++i) b[i] = a[i];
                    root = build(1, cnt, 0); 
                    m += 10000;
                }
            }
            if(opt == 2) 
            {
                read(x1);
                read(y1);
                read(x2);
                read(y2);
                x1 ^= last;
                x2 ^= last;
                y1 ^= last;
                y2 ^= last;
                printf("%d
    ", last = query(root, x1, y1, x2, y2));
            }
            if(opt == 3) break;
        }
    //  fclose(stdin);
    //  fclose(stdout);
        return 0;
    }
    View Code
  • 相关阅读:
    knowledge_maven
    problems_springboot
    problems_halo
    skills_oracle
    hive启动报错(整合spark)
    根据父ID聚合
    sql2005数据库远程备份
    waitfor的使用
    CTE+操作性语句(删除无主键的相同的多行数据)+CTE操作技巧
    SQL中的CTE,查询所有的子集(子集的子集)比游标效率高
  • 原文地址:https://www.cnblogs.com/19992147orz/p/7875161.html
Copyright © 2020-2023  润新知