BZOJ 2626 JZPFAR(KD-tree)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2626

题意:平面上有n个点。现在有m次询问,每次给定一个点(px, py)和一个整数k,输出n个点中离(px, py)的距离第k大的点的标号。如果有两个(或多个)点距离(px, py)相同,那么认为标号较小的点距离较大。

思路:对n个点做KDtree。

 1 #include<algorithm>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<iostream>
 6 #define ll long long
 7 struct Point{
 8     ll d[2],max[2],min[2];
 9     int l,r,id;
10 }a[500005];
11 int root,n,K,cmpd,id[50],m;
12 ll X,Y,ans[50];
13 bool cmp(Point p1,Point p2){
14     if (p1.d[cmpd]!=p2.d[cmpd]) return p1.d[cmpd]<p2.d[cmpd];
15     else return p1.d[!cmpd]<p2.d[!cmpd];
16 }
17 void updata(int x){
18     if (a[x].l){
19         int j=a[x].l;
20         for (int i=0;i<2;i++)
21          a[x].max[i]=std::max(a[x].max[i],a[j].max[i]),
22          a[x].min[i]=std::min(a[x].min[i],a[j].min[i]);
23     }
24     if (a[x].r){
25         int j=a[x].r;
26         for (int i=0;i<2;i++)
27          a[x].max[i]=std::max(a[x].max[i],a[j].max[i]),
28          a[x].min[i]=std::min(a[x].min[i],a[j].min[i]);
29     }
30 }
31 ll sqr(ll x){
32     return x*x;
33 }
34 ll dist(int p,ll x,ll y){
35     ll dis=0,d1,d2;
36     d1=std::abs(x-a[p].max[0]);
37     d2=std::abs(x-a[p].min[0]);
38     if (d1>d2) dis+=d1*d1;
39     else dis+=d2*d2;
40     d1=std::abs(y-a[p].max[1]);
41     d2=std::abs(y-a[p].min[1]);
42     if (d1>d2) dis+=d1*d1;
43     else dis+=d2*d2;
44     return dis;
45 }
46 void query(int p){
47     if (!p) return;
48     ll dl,dr,d0;
49     int t=K;
50     d0=sqr(std::abs(a[p].d[0]-X))+sqr(std::abs(a[p].d[1]-Y));
51     while (t&&(d0>ans[t]||(d0==ans[t]&&a[p].id<id[t]))) t--;
52     if (t!=K){
53      t++;
54      for (int i=K;i>=t+1;i--){
55       ans[i]=ans[i-1];
56       id[i]=id[i-1];
57       }
58      ans[t]=d0;id[t]=a[p].id;
59     }
60     if (a[p].l) dl=dist(a[p].l,X,Y);else dl=0;
61     if (a[p].r) dr=dist(a[p].r,X,Y);else dr=0;
62     if (dl>dr){
63         if (dl>=ans[K]) query(a[p].l);
64         if (dr>=ans[K]) query(a[p].r);
65     }else{
66         if (dr>=ans[K]) query(a[p].r);
67         if (dl>=ans[K]) query(a[p].l);
68     }
69 }
70 int build(int l,int r,int d){
71     int mid=(l+r)/2;
72     cmpd=d;
73     std::nth_element(a+l,a+mid,a+1+r,cmp);
74     a[mid].max[0]=a[mid].min[0]=a[mid].d[0];
75     a[mid].max[1]=a[mid].min[1]=a[mid].d[1];
76     if (l!=mid) a[mid].l=build(l,mid-1,!d);
77     if (r!=mid) a[mid].r=build(mid+1,r,!d);
78     updata(mid);
79     return mid;
80 }
81 int main(){
82     scanf("%d",&n);
83     for (int i=1;i<=n;i++){
84      scanf("%lld%lld",&a[i].d[0],&a[i].d[1]);
85      a[i].id=i;
86     }
87     root=build(1,n,0);
88     scanf("%d",&m);
89     while (m--){
90         scanf("%lld%lld%d",&X,&Y,&K);
91         for (int i=0;i<=20;i++) id[i]=99999999,ans[i]=0;
92         query(root);
93         printf("%d\n",id[K]);
94     }
95 }
时间: 2024-08-23 23:33:08

BZOJ 2626 JZPFAR(KD-tree)的相关文章

简单题(K-D Tree)

简单题不简单-- 我们把单点加操作改成插入一个权值为增加量的点,将问题转化成询问一个矩阵中所有点的和,用 \(K-D\ Tree\) 维护,时间复杂度 \(O(n\sqrt{n})\) \(Code\ Below:\) // luogu-judger-enable-o2 #include <bits/stdc++.h> using namespace std; const int maxn=500000+10; const double alpha=0.75; int n,D,rt,cnt,t

【BZOJ2843】极地旅行社(Link-Cut Tree)

[BZOJ2843]极地旅行社(Link-Cut Tree) 题面 BZOJ 题解 \(LCT\)模板题呀 没什么好说的了.. #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<set> #include<map> #includ

BZOJ 2561 最小生成树(最大流)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2561 题意:给定一个边带正权的连通无向图G= (V,E),其中N=|V|,M=|E|,N个点从1到N依次编号,给定三个正整数u,v,和L (u≠v),假设现在加入一条边权为L的边(u,v),那么需要删掉最少多少条边,才能够使得这条边既可能出现在最小生成树上,也可能出现在最大生成树 上? 思路:考虑克鲁斯卡尔算法的过程.若加入的 边(u,v,L)能够出现在最小生成树中,那么权值小于L的边

BZOJ 2661 连连看(费用流)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2661 题意:给出一个区间[a,b]中的全部整数,如果其中某两个数x,y(设x>y)的平方差x^2-y^2是一个完全平方数z^2,并且y与z互质,那么就可以将x和y一起消除,同时得到x+y点分数.要求就是,消除的数对尽可能多的前提下,得到的分数尽量多. 思路:首先暴力出所有合法的数对(x,y).然后将每个用到的数字拆成两个点,每个数对连一条边.最后的答案除以2即可. struct nod

笔试算法题(51):简介 - 红黑树(RedBlack Tree)

红黑树(Red-Black Tree) 红黑树是一种BST,但是每个节点上增加一个存储位表示该节点的颜色(R或者B):通过对任何一条从root到leaf的路径上节点着色方式的显示,红黑树确保所有路径的差值不会超过一倍,最终使得BST接近平衡: 红黑树内每个节点包含五个属性:color, key, left, right和p,p表示指向父亲节点的指针:一棵BST需要同时满足下述五个性质才能称作红黑树: 每个节点只能是红色或者黑色节点中的一种: 根节点必须是黑色: 每个叶节点(NULL)必须是黑色:

[算法系列之二十四]后缀树(Suffix Tree)

之前有篇文章([算法系列之二十]字典树(Trie))我们详细的介绍了字典树.有了这些基础我们就能更好的理解后缀树了. 一 引言 模式匹配问题 给定一个文本text[0-n-1], 和一个模式串 pattern[0-m-1],写一个函数 search(char pattern[], char text[]), 打印出pattern在text中出现的所有位置(n > m). 这个问题已经有两个经典的算法:KMP算法 ,有限自动机,前者是对模式串pattern做预处理,后者是对待查证文本text做预处

BZOJ 1912 巡逻(树直径)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1912 题意:给出一棵树,边权为1.现在加一条或两条边后,使得从1出发遍历每个点至少一次再回到1的路程最短. 思路:先求一次树的直径Max1.然后将直径的边权改为-1,再求一次直径Max2.答案为ans=(n-1)*2-(Max1-1)-(Max2-1). struct node { int u,v,w,next; }; node edges[N<<1]; int head[N],e;

BZOJ 2331 地板(插头DP)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2331 题意:给出一个n*m的地面.有些是障碍.用L型的地板砖铺满.有多少种方案. 思路:用0表示没有插头,用1表示有插头且可以拐弯,用3表示有插头但是不能再拐弯了. 设有m列,轮廓线为[0,m].对于格子(i,j),设左插头x上插头y,那么转移有: (1)x=0,y=0:此时如图1-0,有三种转移,分别是1-1,1-2,1-3; (2)x!=0,y!=0:此时只有当x=y=1时可以转移

机器学习(三)——决策树(decision tree)算法介绍

0.机器学习中分类和预测算法的评估标准 准确率 速度 强壮性 可规模性 可解释性 1.什么是决策树/判定树(decision tree)? 判定树是一个类似于流程图的树结构:其中,每个内部节点表示一个属性上的测试,每个分支代表一个属性的输出,而每个树叶节点代表类或者类分布.树的最顶层是根节点. 2.机器学习中分类方法的重要算法是决策树 3.构造决策树的基本算法 3.1熵(entropy)概念    信息和抽象,如何度量?1948年,香农提出了 "信息熵(entropy)"的概念,一条信