K-D Tree题目泛做(CXJ第二轮)
题目1: BZOJ 2716
题目大意:给出N个二维平面上的点,M个操作,分为插入一个新点和询问到一个点最近点的Manhatan距离是多少。
算法讨论:
K-D Tree 裸题,有插入操作。
- #include <cstdio>
- #include <iostream>
- #include <cstring>
- #include <cstdlib>
- #include <algorithm>
- using namespace std;
- const int inf = 1e9;
- const int K = ;
- const int N = + ;
- inline int read() {
- int x = ;
- char ch = getchar();
- while(ch < '' || ch > '') ch = getchar();
- while(ch <= '' && ch >= '') {
- x = x * + ch - '';
- ch = getchar();
- }
- return x;
- }
- int n, m, root, D, ans;
- struct Node {
- int d[K], mn[K], mx[K], l, r, v, sum;
- int & operator [] (int x) {
- return d[x];
- }
- Node(int x = , int y = ) {
- l = ; r = ; d[] = x; d[] = y;
- }
- friend bool operator < (Node a, Node b) {
- return a[D] < b[D];
- }
- }p[N], T[N<<], tmp;
- void pushup(int k) {
- Node l = T[T[k].l], r = T[T[k].r];
- for(int i = ; i < K; ++ i) {
- T[k].mn[i] = T[k].mx[i] = T[k][i];
- if(T[k].l) {
- T[k].mn[i] = min(T[k].mn[i], l.mn[i]);
- T[k].mx[i] = max(T[k].mx[i], l.mx[i]);
- }
- if(T[k].r) {
- T[k].mx[i] = max(T[k].mx[i], r.mx[i]);
- T[k].mn[i] = min(T[k].mn[i], r.mn[i]);
- }
- }
- // T[k].sum = T[k].v;
- // if(T[k].l) T[k].sum += l.sum;
- // if(T[k].r) T[k].sum += r.sum;
- }
- int build(int l, int r, int nd) {
- int mid = (l + r) >> ;
- D = nd;
- nth_element(p + l, p + mid, p + r + );
- T[mid] = p[mid];
- T[mid].l = T[mid].r = ;
- for(int i = ; i < K; ++ i)
- T[mid].mx[i] = T[mid].mn[i] = T[mid][i];
- if(l < mid)
- T[mid].l = build(l, mid - , (nd + ) % K);
- if(r > mid)
- T[mid].r = build(mid + , r, (nd + ) % K);
- pushup(mid);
- return mid;
- }
- void insert(int k, int nd) {
- if(tmp[nd] >= T[k][nd]) {
- if(T[k].r) insert(T[k].r, (nd + ) % K);
- else {
- T[k].r = ++ n;
- T[n] = tmp;
- for(int i = ; i < K; ++ i)
- T[n].mn[i] = T[n].mx[i] = T[n][i];
- }
- }
- else {
- if(T[k].l) insert(T[k].l, (nd + ) % K);
- else {
- T[k].l = ++ n;
- T[n] = tmp;
- for(int i = ; i < K; ++ i)
- T[n].mn[i] = T[n].mx[i] = T[n][i];
- }
- }
- pushup(k);
- }
- int getkdis(Node a, Node b) {
- int res = ;
- for(int i = ; i < K; ++ i)
- res += abs(a[i] - b[i]);
- return res;
- }
- int inandout(int k, Node a) {
- int res = ;
- for(int i = ; i < K; ++ i)
- res += max(, T[k].mn[i] - a[i]);
- for(int i = ; i < K; ++ i)
- res += max(, a[i] - T[k].mx[i]);
- return res;
- }
- void query(int k, int nd) {
- int d, dl = inf, dr = inf;
- d = getkdis(T[k], tmp);
- if(d) ans = min(ans, d);
- if(T[k].l) dl = inandout(T[k].l, tmp);
- if(T[k].r) dr = inandout(T[k].r, tmp);
- if(dl < dr) {
- if(dl < ans) query(T[k].l, (nd + ) % K);
- if(dr < ans) query(T[k].r, (nd + ) % K);
- }
- else {
- if(dr < ans) query(T[k].r, (nd + ) % K);
- if(dl < ans) query(T[k].l, (nd + ) % K);
- }
- }
- int query(Node a) {
- tmp = a; ans = inf;
- query(root, );
- return ans;
- }
- void insert(Node a) {
- tmp = a; insert(root, );
- }
- #define ONLINE_JUDGE
- int main() {
- #ifndef ONLINE_JUDGE
- freopen("1.in", "r", stdin);
- freopen("1.out", "w", stdout);
- #endif
- int type, x, y;
- n = read(); m = read();
- for(int i = ; i <= n; ++ i)
- p[i][] = read(), p[i][] = read();
- root = build(, n, );//忘记写root等于了。
- for(int i = ; i <= m; ++ i) {
- type = read(); x = read(); y = read();
- if(type == ) insert(Node(x, y));
- else printf("%d\n", query(Node(x, y)));
- }
- #ifndef ONLINE_JUDGE
- fclose(stdin); fclose(stdout);
- #endif
- return ;
- }
BZOJ 2716
题目2: BZOJ 1941
题目大意:给出N个点,求对于每个点说,Manhantan距离最远点与最近点的差值最小是多少。
算法讨论:
K-D Tree裸题,注意最近点不能是自己。
- #include <cstdio>
- #include <iostream>
- #include <cstring>
- #include <cstdlib>
- #include <algorithm>
- using namespace std;
- const int N = + ;
- const int inf = 1e9;
- const int K = ;
- inline int read() {
- int x = ;
- char ch = getchar();
- while(ch < '' || ch > '') ch = getchar();
- while(ch <= '' && ch >= '') {
- x = x * + ch - '';
- ch = getchar();
- }
- return x;
- }
- int n, root, amax, amin, D;
- struct Node {
- int d[K], mn[K], mx[K], l, r;
- int & operator [] (int x) {
- return d[x];
- }
- Node (int x = , int y = ) {
- l = ; r = ; d[] = x; d[] = y;
- }
- friend bool operator < (Node a, Node b) {
- return a[D] < b[D];
- }
- }p[N], T[N<<], tmp;
- void pushup(int k) {
- Node l = T[T[k].l], r = T[T[k].r];
- for(int i = ; i < K; ++ i) {
- T[k].mn[i] = T[k].mx[i] = T[k][i];
- if(T[k].l) {
- T[k].mx[i] = max(T[k].mx[i], l.mx[i]);
- T[k].mn[i] = min(T[k].mn[i], l.mn[i]);
- }
- if(T[k].r) {
- T[k].mx[i] = max(T[k].mx[i], r.mx[i]);
- T[k].mn[i] = min(T[k].mn[i], r.mn[i]);
- }
- }
- }
- int build(int l, int r, int nd) {
- int mid = (l + r) >> ;
- D = nd;
- nth_element(p + l, p + mid, p + r + );
- T[mid] = p[mid];
- T[mid].l = T[mid].r = ;
- for(int i = ; i < K; ++ i)
- T[mid].mn[i] = T[mid].mx[i] = T[mid][i];
- if(l < mid) T[mid].l = build(l, mid - , (D + ) % K);
- if(r > mid) T[mid].r = build(mid + , r, (D + ) % K);
- pushup(mid);
- return mid;
- }
- void insert(int k, int nd) {
- if(tmp[nd] >= T[k][nd]) {
- if(T[k].r) insert(T[k].r, (nd + ) % K);
- else {
- T[k].r = ++ n;
- T[n] = tmp;
- for(int i = ; i < K; ++ i)
- T[n].mx[i] = T[n].mn[i] = T[n][i];
- }
- }
- else {
- if(T[k].l) insert(T[k].l, (nd + ) % K);
- else {
- T[k].l = ++ n;
- T[n] = tmp;
- for(int i = ; i < K; ++ i)
- T[n].mx[i] = T[n].mn[i] = T[n][i];
- }
- }
- pushup(k);
- }
- int getkdis(Node a, Node b) {
- int res = ;
- for(int i = ; i < K; ++ i)
- res += abs(a[i] - b[i]);
- return res;
- }
- int outandin(int k, Node q) {
- int res = ;
- for(int i = ; i < K; ++ i)
- res += max(, T[k].mn[i] - q[i]);
- for(int i = ; i < K; ++ i)
- res += max(, q[i] - T[k].mx[i]);
- return res;
- }
- int outandinmaxx(int k, Node q) {
- int res = ;
- for(int i = ; i < K; ++ i)
- res += max(abs(T[k].mn[i] - q[i]), abs(T[k].mx[i] - q[i]));
- return res;
- }
- void query_maxx(int k, int nd) {
- int d, dl = -inf, dr = -inf;
- d = getkdis(T[k], tmp);
- amax = max(d, amax);
- if(T[k].l) dl = outandinmaxx(T[k].l, tmp);
- if(T[k].r) dr = outandinmaxx(T[k].r, tmp);
- if(dl > dr) {
- if(dl > amax) query_maxx(T[k].l, (nd + ) % K);
- if(dr > amax) query_maxx(T[k].r, (nd + ) % K);
- }
- else {
- if(dr > amax) query_maxx(T[k].r, (nd + ) % K);
- if(dl > amax) query_maxx(T[k].l, (nd + ) % K);
- }
- }
- void query_minn(int k, int nd) {
- int d, dl = inf, dr = inf;
- d = getkdis(T[k], tmp);
- if(d) amin = min(d, amin);
- if(T[k].l) dl = outandin(T[k].l, tmp);
- if(T[k].r) dr = outandin(T[k].r, tmp);
- if(dl < dr) {
- if(dl < amin) query_minn(T[k].l, (nd + ) % K);
- if(dr < amin) query_minn(T[k].r, (nd + ) % K);
- }
- else {
- if(dr < amin) query_minn(T[k].r, (nd + ) % K);
- if(dl < amin) query_minn(T[k].l, (nd + ) % K);
- }
- }
- void qmax(int l) {
- amax = -inf; tmp = p[l];
- query_maxx(root, );
- }
- void qmin(int l) {
- amin = inf; tmp = p[l];
- query_minn(root, );
- }
- int main() {
- int outans = inf;
- n = read();
- for(int i = ; i <= n; ++ i) {
- p[i][] = read(); p[i][] = read();
- }
- root = build(, n, );
- for(int i = ; i <= n; ++ i) {
- qmax(i); qmin(i);
- outans = min(outans, amax - amin);
- }
- printf("%d\n", outans);
- return ;
- }
BZOJ 1941
题目3: BZOJ4520 && CQOI 2016 K远点对查询
题目大意:
给出n个二维平面上的点,求第k远的点对距离是多少。(欧几里德距离的平方)
算法讨论:
1、为了防止重复,小根堆里面保存2*K个元素。
2、编程习惯一定要好。同类型比较,减少强制类型转制。在查询欧几里德距离的时候,query中的维度参数是没有用的。
果断要去掉。否则就是TLE和AC的区别。
要区分好查询欧几里德距离和曼哈顿距离时两者的区别。
代码:
- #include <cstdlib>
- #include <cstdio>
- #include <iostream>
- #include <cstring>
- #include <algorithm>
- #include <cctype>
- #include <queue>
- #include <vector>
- using namespace std;
- typedef long long ll;
- const int N = 100000 + 5;
- const int K = 2;
- const ll inf = 10000000000000LL;
- inline int read() {
- int x = 0; char c = getchar();
- while(!isdigit(c)) c = getchar();
- while(isdigit(c)) {
- x = x * 10 + c - '0';
- c = getchar();
- }
- return x;
- }
- int buf[20];
- inline void output(ll x) {
- int p = 0; buf[0] = 0;
- if(!x) p ++;
- else {
- while(x) {
- buf[p ++] = x % 10;
- x /= 10;
- }
- }
- for(int i = p - 1; i >= 0; -- i)
- putchar(buf[i] + '0');
- }
- int root, n, kk, D;
- priority_queue <ll, vector<ll>, greater<ll> > ans;
- struct Node {
- int l, r;
- ll d[K], mn[K], mx[K];
- Node(ll x = 0, ll y = 0) {
- l = r = 0; d[0] = x; d[1] = y;
- }
- ll & operator [] (int x) { return d[x];}
- friend bool operator < (Node a, Node b) {
- return a[D] < b[D];
- }
- }p[N], T[N << 1], tmp;
- void pushup(int k) {
- Node l = T[T[k].l], r = T[T[k].r];
- for(int i = 0; i < K; ++ i) {
- T[k].mx[i] = T[k].mn[i] = T[k][i];
- if(T[k].l) {
- T[k].mx[i] = max(T[k].mx[i], l.mx[i]);
- T[k].mn[i] = min(T[k].mn[i], l.mn[i]);
- }
- if(T[k].r) {
- T[k].mx[i] = max(T[k].mx[i], r.mx[i]);
- T[k].mn[i] = min(T[k].mn[i], r.mn[i]);
- }
- }
- }
- int build(int l, int r, int nd) {
- int mid = (l + r) >> 1;
- D = nd;
- nth_element(p + l, p + mid, p + r + 1);
- T[mid] = p[mid];
- T[mid].l = T[mid].r = 0;
- for(int i = 0; i < K; ++ i)
- T[mid].mx[i] = T[mid].mn[i] = T[mid][i];
- if(l < mid) T[mid].l = build(l, mid - 1, (nd + 1) % K);
- if(r > mid) T[mid].r = build(mid + 1, r, (nd + 1) % K);
- pushup(mid);
- return mid;
- }
- ll geteulerdis(Node a, Node b) {//竭诚为欧几里德距离服务
- ll res = 0;
- for(int i = 0; i < K; ++ i)
- res += (a[i] - b[i]) * (a[i] - b[i]);
- return res;
- }
- ll outandineuler(Node a) {
- ll L = 0;
- L = max(L, geteulerdis(tmp, Node(a.mx[0], a.mn[1])));
- L = max(L, geteulerdis(tmp, Node(a.mx[0], a.mx[1])));
- L = max(L, geteulerdis(tmp, Node(a.mn[0], a.mn[1])));
- L = max(L, geteulerdis(tmp, Node(a.mn[0], a.mx[1])));
- return L;
- }
- void query(int k) {
- ll d, dl = -inf, dr = -inf;
- d = geteulerdis(T[k], tmp);
- if(d > ans.top()) {
- ans.pop(); ans.push(d);
- }
- if(T[k].l) dl = outandineuler(T[T[k].l]);
- if(T[k].r) dr = outandineuler(T[T[k].r]);
- if(dl > dr) {
- if(dl > ans.top()) query(T[k].l);
- if(dr > ans.top()) query(T[k].r);
- }
- else {
- if(dr > ans.top()) query(T[k].r);
- if(dl > ans.top()) query(T[k].l);
- }
- }
- void Q(int i) {
- tmp = p[i];
- query(root);
- }
- int main() {
- n = read(); kk = read();
- for(int i = 1; i <= 2 * kk; ++ i) ans.push(0);
- for(int i = 1; i <= n; ++ i) {
- p[i][0] = read(); p[i][1] = read();
- }
- root = build(1, n, 0);
- for(int i = 1; i <= n; ++ i) Q(i);
- output(ans.top());
- return 0;
- }
K-D Tree题目泛做(CXJ第二轮)的更多相关文章
- 基尔霍夫矩阵题目泛做(AD第二轮)
题目1: SPOJ 2832 题目大意: 求一个矩阵行列式模一个数P后的值.p不一定是质数. 算法讨论: 因为有除法而且p不一定是质数,不一定有逆元,所以我们用辗转相除法. #include < ...
- 生成树题目泛做(AD第二轮)
题目1: NOI2014 魔法森林 LCT维护MST.解题报告见LOFTER #include <cstdio> #include <iostream> #include &l ...
- FFT与多项式、生成函数题目泛做
题目1 COGS 很强的乘法问题 高精度乘法用FFT加速 #include <cstdlib> #include <iostream> #include <algorit ...
- 二维计算几何基础题目泛做(SYX第一轮)
题目1: POJ 2318 TOYS 题目大意: 给一个有n个挡板的盒子,从左到右空格编号为0...n.有好多玩具,问每个玩具在哪个空格里面. 算法讨论: 直接叉积判断就可以.注意在盒子的边界上面也算 ...
- 后缀自动机/回文自动机/AC自动机/序列自动机----各种自动机(自冻鸡) 题目泛做
题目1 BZOJ 3676 APIO2014 回文串 算法讨论: cnt表示回文自动机上每个结点回文串出现的次数.这是回文自动机的定义考查题. #include <cstdlib> #in ...
- Link-Cut-Tree题目泛做(为了对应自己的课件)
题目1:BZOJ 2049 洞穴勘测 #include <bits/stdc++.h> #define L(x) c[x][0] #define R(x) c[x][1] using na ...
- 【长期计划】Atcoder题目泛做
之前学长跟我说的是700-的应该都能自己做? 然后1000-的应该都能有一定的思路? 记不清了 但总之是要智力康复一下 又加上文化课比较紧 所以这个大概就会是长期计划了 ————————————分鸽线 ...
- 插头DP题目泛做(为了对应WYD的课件)
题目1:BZOJ 1814 URAL 1519 Formula 1 题目大意:给定一个N*M的棋盘,上面有障碍格子.求一个经过所有非障碍格子形成的回路的数量. 插头DP入门题.记录连通分量. #inc ...
- 数学期望和概率DP题目泛做(为了对应AD的课件)
题1: Uva 1636 Headshot 题目大意: 给出一个000111序列,注意实际上是环状的.问是0出现的概率大,还是当前是0,下一个还是0的概率大. 问题比较简单,注意比较大小: A/C & ...
随机推荐
- MySQL 数据库操作命令汇总
此文全部都是基本的数据库语言 1.登陆到mysql >mysql -h hostname -u username -p 然后等待系统提示输入密码即可登陆.如果想在登陆的时候就选择好数据库,可以使 ...
- My SQL 常用函数
一.数学函数 数学函数主要用于处理数字,包括整型.浮点数等. ABS(x) 返回x的绝对值 SELECT ABS(-1) -- 返回1 CEIL(x),CEILING(x) 返回大于或等于x的最小整数 ...
- 搭建Nuget
1. 新建一个 ASP.NET 空Web应用程序 2. 在新建的项目中引用 安装 NuGet.Server 2.1 右键项目中的引用,出现一个“管理NuGet程序包(N)”,点击进入 2.2 在搜 ...
- xcode5.1上真机调试报告No architectures to compile for...的解决办法
由于手头上只有一台IPAD一代,近期升级到IOS5.0了(人家apple只让升级到此为止)而开发环境Xcode版本是5.1,默认情况下XCode编译出来的代码最低能跑在IOS6.0下, 于是GOOGL ...
- Python 学习日记(第四周)
set数据类型 先用一行代码来说明一下 #!/usr/bin/env python s2={} s = {33,12,33,32121} for i in s: print(i) print(type ...
- vuex构建笔记本应用学习
vuex:针对vue应用派生的专门管理应用state的工具,state可以理解为我们组件需要操作的data数据,都知道,vue构建spa应用的时候,随着组件规模的提升,各个子组件之间的通信如果采用子组 ...
- android 反编译操作
1:首先将apk程序解压: 2:将classes.dex反编译为jar包:$ ./dex2jar/dex2jar.sh classes.dex 将生成一个新的文件classes_dex2jar.jar ...
- 从vector容器中查找一个子串:search()算法
如果要从vector容器中查找是否存在一个子串序列,就像从一个字符串中查找子串那样,次数find()与find_if()算法就不起作用了,需要采用search()算法:例子: #include &qu ...
- UNIX网络编程--ioctl操作(十七)
一.概述 在本书中有两个地方都对这个函数进行了介绍,其实还有很多地方需要这个函数.ioclt函数传统上一直作为纳西而不适合归入其他精细定义类别的特性的系统接口.网络程序(特别是服务器程序)经常在程序启 ...
- 【转】将Vim改造为强大的IDE—Vim集成Ctags/Taglist/Cscope/Winmanager/NERDTree/OmniCppComplete(有图有真相)
原文网址:http://blog.csdn.net/bokee/article/details/6633193 工欲善其事,必先利其器.一个强大的开发环境可以大大提高工作效率.好吧,我知道这是废话.. ...