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 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的老爷机快呀。。。)
转载于:https://www.cnblogs.com/galaxies/p/bzoj4605.html
bzoj4605 崂山白花蛇草水相关推荐
- bzoj4605: 崂山白花蛇草水 权值线段树套KDtree
bzoj4605: 崂山白花蛇草水 链接 bzoj loj 思路 强制在线,那就权值线段树套KDtree好了,没啥好讲的. KDtree要加平衡因子来重构.另外,那水真难喝. 错误 树套树一边写过了, ...
- bzoj4605: 崂山白花蛇草水 //替罪羊式重构k-d树
bzoj4605: 崂山白花蛇草水 题意 Q(<=100000)次操作,支持: 在二维平面上插入一个坐标(x,y)(x,y<=500000),点权为v(<=1e9)的点: 查询矩形区 ...
- [bzoj4605]崂山白花蛇草水 k-d tree 带替罪羊重构
4605: 崂山白花蛇草水 Time Limit: 80 Sec Memory Limit: 512 MB [Submit][Status][Discuss] Description 神犇Aleph ...
- 【线段树套KD树】[BZOJ4605]崂山白花蛇草水
题目描述 Description 神犇Aleph在SDOI Round2前立了一个flag:如果进了省队,就现场直播喝崂山白花蛇草水.凭借着神犇Aleph的实 力,他轻松地进了山东省省队,现在便是他履 ...
- bzoj4605 崂山白花蛇草水 权值线段树套kd树
Description Q次操作,要求资瓷 在(x,y)处放一个数字x 查询(x1,y1)到(x2,y2)矩形内第k大 Solution 非常裸的权值线段树套kd树,为了保证复杂度可以定期重构也可以平 ...
- BZOJ4605 : 崂山白花蛇草水
外层维护权值线段树,内层维护kd-tree. 修改的时候只往右儿子里插入,不平衡的时候替罪羊式重构. 查询的时候在外层线段树上走,在内层kd-tree上查询矩形内点数即可. 时间复杂度$O(q\log ...
- bzoj4605 崂山白花蛇草水(动态开点线段树逃替罪羊重构K-D tree)
首先我们发现它是一个三维的问题而且还强制在线 囧 我们可以考虑在外面来一个权值线段树,然后每次查询时在线段树二分即可,这样我们每个节点再套一棵K-D tree,用来查询有多少个点被框住了,然后因为是不 ...
- bzoj4605: 崂山白花蛇草水(权值线段树套k-dtree)
题目 #include<bits/stdc++.h> using namespace std; #define mid (l+r>>1) const int N=100002, ...
- [BZOJ4605]崂山白花蛇草水(主席树套kd-tree)
题意:两种操作,在二维平面插入一个点及其权值,查询矩形区间第k大,强制在线. 之前考试考过一个矩形区间第k大的题..当时想了各种树套树套树,算了算复杂度都没有暴力快..后来憋了个kd-tree套主席树 ...
最新文章
- 图片增强深度学习deep learning keras
- quartus总线怎样连接(例如,怎么和ROM连接)
- Scott Mitchell 的ASP.NET 2.0数据教程之二十一:: 实现开放式并发
- go:系统参数or函数--未完
- webpack之proxyTable配置
- factorybean 代理类不能按照类型注入_《Spring入门经典》:使用Spring进行依赖注入
- Django(part37)--session
- 灰度图的width和widthstep的区别
- 使用Spring Form标签探索Spring Controller
- 安编译器错误_centos 安装pcre报c++编译器错误
- Swift入坑系列—集合类型
- 机器学习分类模型评价指标和方法
- python 合并不同文件夹下名称相同的文件
- 手把手教你在VM虚拟机上安装windows11
- svnserver 重新启动
- 基于ESP32CAM实现WebSocket服务器实时点灯
- 大数据行业必须掌握的核心技术
- 万邦淘宝/天猫按关键字搜索淘宝商品 API 返回值
- 不是吧!做了3年Android还没看过OkHttp源码?好吧,带你彻底理解一波!
- 头歌实践教学平台——python程序设计——元组的使用