糖尿病康复,内容丰富有趣,生活中的好帮手!
糖尿病康复 > bzoj4605 崂山白花蛇草水

bzoj4605 崂山白花蛇草水

时间:2020-01-30 04:45:01

相关推荐

bzoj4605 崂山白花蛇草水

传送门:/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 staticint 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].rinline 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 rsint 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\n", 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 staticint 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].rinline 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 rsint 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\n", lst = sum(root, 1, 1e9, v));}// if(Q % 10000 == 0) cerr << Q << endl; }return 0;}

View Code

贴两张lemon的测的图

上面这张是第一份代码

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

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

如果觉得《bzoj4605 崂山白花蛇草水》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。