zoukankan      html  css  js  c++  java
  • bzoj4605 崂山白花蛇草水

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4605

    【题解】

    序列上的第k大我们可以用线段树内套一个能查询序列某些地方有多少数的数据结构来做。

    那么平面上很显然就是kdtree。

    然后我们要调调重构块大小,大概是2000.

    然后发现这样还是很慢,发现一个可以优化的地方,线段树上如果这个节点是父亲的左孩子,那么不用存储。

    因为我们只会查询右孩子来判断往那里走。

    这样就能过啦!要跑50s啊。。。

    # include <stdio.h>
    # include <assert.h>
    # include <string.h>
    # include <iostream>
    # include <algorithm>
    // # include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int M = 5e5 + 10, N = 5e6 + 10;
    const int mod = 1e9+7;
    
    # define RG register
    # define ST static
    
    int n, Q;
    int REBUILD_SIZE = 2000;
    
    inline int read() {
        int x = 0, f = 1; char ch = getchar();
        while(!isdigit(ch)) {
            if(ch == '-') f = -1;
            ch = getchar();
        }
        while(isdigit(ch)) {
            x = (x<<3) + (x<<1) + ch - '0';
            ch = getchar();
        }
        return f == 1 ? x : -x;
    }
    
    int D;
    struct node {
        int d[2], mx[2], mi[2], l, r, siz, v, s;
        friend bool operator ==(node a, node b) {
            return a.d[0] == b.d[0] && a.d[1] == b.d[1];
        }
        friend bool operator <(node a, node b) {
            return a.d[D] < b.d[D];
        }
    };
    
    # define ls T[x].l
    # define rs T[x].r
    
    inline void gmax(int &x, int y) {
        if(x < y) x = y;
    }
    inline void gmin(int &x, int y) {
        if(x > y) x = y;
    }
    
    inline bool in(int x1, int y1, int x2, int y2, int xx1, int yy1, int xx2, int yy2) {
        return x1 <= xx1 && xx2 <= x2 && y1 <= yy1 && yy2 <= y2;    
    }
    
    inline bool out(int x1, int y1, int x2, int y2, int xx1, int yy1, int xx2, int yy2) {
        return x1 > xx2 || x2 < xx1 || y1 > yy2 || y2 < yy1;
    }
    
    inline bool cmp(int, int);
    
    node tmp;
    struct KDT {
        node T[N];
        int siz;
        int t[M], tn;
        inline void set() {
            siz = 0; T[0].siz = 0, T[0].s = 0;
        }
        inline void up(int x) {
            for (int i=0; i<2; ++i) {
                T[x].mi[i] = T[x].mx[i] = T[x].d[i];
                if(ls) gmin(T[x].mi[i], T[ls].mi[i]);
                if(rs) gmin(T[x].mi[i], T[rs].mi[i]);
                if(ls) gmax(T[x].mx[i], T[ls].mx[i]);
                if(rs) gmax(T[x].mx[i], T[rs].mx[i]);
            }
            T[x].s = T[x].v + T[ls].s + T[rs].s;
            T[x].siz = 1 + T[ls].siz + T[rs].siz;
        }
        inline void insert(int &x, int d) {
            if(!x) {
                x = ++siz;
                T[x].d[0] = T[x].mi[0] = T[x].mx[0] = tmp.d[0];
                T[x].d[1] = T[x].mi[1] = T[x].mx[1] = tmp.d[1];
                T[x].siz = 1;
            }
            if(tmp == T[x]) {
                T[x].v += tmp.v;
                T[x].s += tmp.v;
                return ;
            }
            if(tmp.d[d] < T[x].d[d]) insert(ls, d^1);
            else insert(rs, d^1);
            up(x);
        }
        inline 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, T[x].mi[0], T[x].mi[1], T[x].mx[0], T[x].mx[1])) return T[x].s;
            if(out(x1, y1, x2, y2, T[x].mi[0], T[x].mi[1], T[x].mx[0], T[x].mx[1])) return 0;
            if(in(x1, y1, x2, y2, T[x].d[0], T[x].d[1], T[x].d[0], T[x].d[1])) ret += T[x].v;
            ret += query(ls, x1, y1, x2, y2) + query(rs, x1, y1, x2, y2);
            return ret;
        }
        inline void getnode(int x) {
            if(!x) return ;
            getnode(ls);
            getnode(rs);
            t[++tn] = x;
        }
        inline int build(int l, int r, int d) {
            if(l>r) return 0;
            int mid = l+r>>1; D = d;
            nth_element(t+l, t+mid, t+r+1, cmp);
            int x = t[mid];
            T[x].l = build(l, mid-1, d^1);
            T[x].r = build(mid+1, r, d^1);
            up(x);
            return x;
        }
        inline int rebuild(int x, int d) {
            tn = 0;
            getnode(x);
            return build(1, tn, d);
        }
    }T;
    
    inline bool cmp(int a, int b) {
        return T.T[a] < T.T[b];
    }
    
    # undef ls
    # undef rs
    
    int xs, ys, xx, yy;
    int rt[N], L[N], R[N];
    int rb[N], siz, root;
    
    inline void modify(int &x, int l, int r, int v, bool b) {
        if(!x) x = ++siz, rb[x] = REBUILD_SIZE;
        if(b) {
            T.insert(rt[x], 0);
            if(T.T[rt[x]].siz == rb[x]) {
                rt[x] = T.rebuild(rt[x], 0);
                rb[x] += REBUILD_SIZE;
            }
        }
        if(l == r) return ;
        int mid = l+r>>1;
        if(v <= mid) modify(L[x], l, mid, v, 0);
        else modify(R[x], mid+1, r, v, 1);
    }
    
    inline int sum(int x, int l, int r, int k) {
        if(l == r) return l;
        int t = T.query(rt[R[x]], xs, ys, xx, yy);
        int mid = l+r>>1;
        if(k <= t) return sum(R[x], mid+1, r, k);
        else return sum(L[x], l, mid, k-t);
    }
    
    int main() {
    //    freopen("4605.in", "r", stdin);
    //    freopen("4605.out", "w", stdout);
        int opt, v, lst = 0;
        n = read(), Q = read();
        T.set();
        while(Q--) {
            opt = read();
            if(opt == 1) {
    //            xs = read(), ys = read(), v = read();
                xs = read() ^ lst, ys = read() ^ lst, v = read() ^ lst;
                tmp.d[0] = xs, tmp.d[1] = ys, tmp.v = tmp.s = 1;
                modify(root, 1, 1e9, v, 1);
            }
            if(opt == 2) {
    //            xs = read(), ys = read(), xx = read(), yy = read(), v = read();
                xs = read() ^ lst, ys = read() ^ lst, xx = read() ^ lst, yy = read() ^ lst, v = read() ^ lst;
                int t = T.query(rt[root], xs, ys, xx, yy);        
                if(t < v) puts("NAIVE!ORZzyz."), lst = 0;
                else printf("%d
    ", lst = sum(root, 1, 1e9, v));
            }
    //        if(Q % 10000 == 0) cerr << Q << endl;
        }
        return 0;
    }
    View Code

    当然放在外面写不大好

    正宗的替罪羊式kdtree,是在里面写的,插入的时候顺便记录深度。

    取参数A约在0.7左右,然B=log(1.0/A)

    那么当深度超过子树大小/B的时候就加入重构标志。

    如果同时满足子树大小>总子树大小*A,那么就重构。

    (记住就好啦。。。)

    然后这复杂度就很优秀了。

    # include <math.h>
    # include <stdio.h>
    # include <assert.h>
    # include <string.h>
    # include <iostream>
    # include <algorithm>
    // # include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int M = 5e5 + 10, N = 5e6 + 10;
    const int mod = 1e9+7;
    
    # define RG register
    # define ST static
    
    int n, Q;
    const double REBUILD_FAC = 0.713, REBUILD_LOG = log(1.0 - REBUILD_FAC);
    const int REBUILD_SIZE = 2000;
    
    inline int read() {
        int x = 0, f = 1; char ch = getchar();
        while(!isdigit(ch)) {
            if(ch == '-') f = -1;
            ch = getchar();
        }
        while(isdigit(ch)) {
            x = (x<<3) + (x<<1) + ch - '0';
            ch = getchar();
        }
        return f == 1 ? x : -x;
    }
    
    int D;
    struct node {
        int d[2], mx[2], mi[2], l, r, siz, v, s;
        friend bool operator ==(node a, node b) {
            return a.d[0] == b.d[0] && a.d[1] == b.d[1];
        }
        friend bool operator <(node a, node b) {
            return a.d[D] < b.d[D];
        }
    };
    
    # define ls T[x].l
    # define rs T[x].r
    
    inline void gmax(int &x, int y) {
        if(x < y) x = y;
    }
    inline void gmin(int &x, int y) {
        if(x > y) x = y;
    }
    
    inline bool in(int x1, int y1, int x2, int y2, int xx1, int yy1, int xx2, int yy2) {
        return x1 <= xx1 && xx2 <= x2 && y1 <= yy1 && yy2 <= y2;    
    }
    
    inline bool out(int x1, int y1, int x2, int y2, int xx1, int yy1, int xx2, int yy2) {
        return x1 > xx2 || x2 < xx1 || y1 > yy2 || y2 < yy1;
    }
    
    inline bool cmp(int, int);
    
    int rt[N], psx;
    node tmp;
    struct KDT {
        node T[N];
        int siz;
        int t[M], tn;
        inline void set() {
            siz = 0; T[0].siz = 0, T[0].s = 0;
        }
        inline void up(int x) {
            for (int i=0; i<2; ++i) {
                T[x].mi[i] = T[x].mx[i] = T[x].d[i];
                if(ls) gmin(T[x].mi[i], T[ls].mi[i]);
                if(rs) gmin(T[x].mi[i], T[rs].mi[i]);
                if(ls) gmax(T[x].mx[i], T[ls].mx[i]);
                if(rs) gmax(T[x].mx[i], T[rs].mx[i]);
            }
            T[x].s = T[x].v + T[ls].s + T[rs].s;
            T[x].siz = 1 + T[ls].siz + T[rs].siz;
        }
        inline bool insert(int &x, int d, int dep) {
            if(!x) {
                x = ++siz;
                T[x].d[0] = T[x].mi[0] = T[x].mx[0] = tmp.d[0];
                T[x].d[1] = T[x].mi[1] = T[x].mx[1] = tmp.d[1];
                T[x].siz = 1; T[x].v = tmp.v, T[x].s = tmp.s;
                return dep > log(T[rt[psx]].siz)/REBUILD_LOG;
            }
            int id; bool ret;
            if(tmp.d[d] < T[x].d[d]) id = ls, ret = insert(ls, d^1, dep+1);
            else id = rs, ret = insert(rs, d^1, dep+1);
            up(x);
            if(ret) {
                if(T[id].siz > REBUILD_FAC * T[x].siz) {
                    x = rebuild(x, d);
                    return 0;
                }
                return 1;
            }
            return 0;
        }
        inline 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, T[x].mi[0], T[x].mi[1], T[x].mx[0], T[x].mx[1])) return T[x].s;
            if(out(x1, y1, x2, y2, T[x].mi[0], T[x].mi[1], T[x].mx[0], T[x].mx[1])) return 0;
            if(in(x1, y1, x2, y2, T[x].d[0], T[x].d[1], T[x].d[0], T[x].d[1])) ret += T[x].v;
            ret += query(ls, x1, y1, x2, y2) + query(rs, x1, y1, x2, y2);
            return ret;
        }
        inline void getnode(int x) {
            if(!x) return ;
            getnode(ls);
            getnode(rs);
            t[++tn] = x;
        }
        inline int build(int l, int r, int d) {
            if(l>r) return 0;
            int mid = l+r>>1; D = d;
            nth_element(t+l, t+mid, t+r+1, cmp);
            int x = t[mid];
            T[x].l = build(l, mid-1, d^1);
            T[x].r = build(mid+1, r, d^1);
            up(x);
            return x;
        }
        inline int rebuild(int x, int d) {
            tn = 0;
            getnode(x);
            return build(1, tn, d);
        }
    }T;
    
    inline bool cmp(int a, int b) {
        return T.T[a] < T.T[b];
    }
    
    # undef ls
    # undef rs
    
    int xs, ys, xx, yy;
    int L[N], R[N];
    int siz, root;
    
    inline void modify(int &x, int l, int r, int v, bool b) {
        if(!x) x = ++siz;
        if(b) {
            psx = x; 
            T.insert(rt[x], 0, 0);
        }
        if(l == r) return ;
        int mid = l+r>>1;
        if(v <= mid) modify(L[x], l, mid, v, 0);
        else modify(R[x], mid+1, r, v, 1);
    }
    
    inline int sum(int x, int l, int r, int k) {
        if(l == r) return l;
        int t = T.query(rt[R[x]], xs, ys, xx, yy);
        int mid = l+r>>1;
        if(k <= t) return sum(R[x], mid+1, r, k);
        else return sum(L[x], l, mid, k-t);
    }
    
    int main() {
    //    freopen("4605.in", "r", stdin);
    //    freopen("4605.out", "w", stdout);
        int opt, v, lst = 0;
        n = read(), Q = read();
        T.set();
        while(Q--) {
            opt = read();
            if(opt == 1) {
    //            xs = read(), ys = read(), v = read();
                xs = read() ^ lst, ys = read() ^ lst, v = read() ^ lst;
                tmp.d[0] = xs, tmp.d[1] = ys, tmp.v = tmp.s = 1;
                modify(root, 1, 1e9, v, 1);
            }
            if(opt == 2) {
    //            xs = read(), ys = read(), xx = read(), yy = read(), v = read();
                xs = read() ^ lst, ys = read() ^ lst, xx = read() ^ lst, yy = read() ^ lst, v = read() ^ lst;
                int t = T.query(rt[root], xs, ys, xx, yy);        
                if(t < v) puts("NAIVE!ORZzyz."), lst = 0;
                else printf("%d
    ", lst = sum(root, 1, 1e9, v));
            }
    //        if(Q % 10000 == 0) cerr << Q << endl;
        }
        return 0;
    }
    View Code

    贴两张lemon的测的图

    上面这张是第一份代码

    下面是第二张代码,在bzoj跑19s。

    (我的老爷机比bzoj的老爷机快呀。。。)

  • 相关阅读:
    C
    A
    hdu 三部曲1 Popular Cows tarjan算法&&缩点&&拓扑排序
    hdu 三部曲 Going Home 最小费用最大流 EK算法
    hdu 三部曲 1Minimum Cost 最小费用最大流EK算法
    hdu 三部曲1 Is the Information Reliable? 差分约束 bellman_ford算法
    hdu 三部曲1 Intervals 差分约束问题 spfa算法
    hdu 三部曲 Crashing Robots
    hdu 三部曲2 Rebuilding Roads
    Codeforces 1277C As Simple as One and Two
  • 原文地址:https://www.cnblogs.com/galaxies/p/bzoj4605.html
Copyright © 2011-2022 走看看