KDT的坑...
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了KDT的坑...相关的知识,希望对你有一定的参考价值。
诶最近开坑好频繁啊...感觉没救了TAT
写了几道模板题.....
建树
比如现在有一些二维平面上的点,我们按照维度首先进行一次划分:
比如第一次划分x维,那么我们找到所有点中x坐标为中位数的点,将其作为根,x坐标小于中位数的点划分到左子树,否则划分到右子树。然后递归划分剩余的两侧的点。下一次划分依据为y维,再下一次划分依据为x维。以此类推。
每个节点存储的信息包含为以这个点为根的子树所有的点的矩形的左上角和右下角的坐标。我们在划分结束时更新即可。
那么我们如何查询到一个给定坐标(x,y)曼哈顿距离最近的点呢?
记录全局变量ans,表示目前的最小距离。初值设为INF.
从根节点开始,递归向下查询:首先用当前节点更新答案,随后看左右子树所对应的矩形,若询问点在矩形外,矩形距离的询问点到这个矩形的最近距离,否则为0.
我们优先选择矩形距离比较小的一侧递归向下询问。询问之后,若另一侧的矩形距离不大于当前的最优解,则再询问另一侧。
据神犇说这个过程是最坏O(sqrt(n))的。
考虑插入。
维护一下目前划分的依据是哪一维。
从根开始递归向下插入。
首先用插入点更新当前节点,然后判断一下是应该插入到当前节点的左子树还是右子树,若插入的部分为空,直接插入;否则再递归插入。
2716&&2648 双倍经验....两边一起交+两边一起wa非常爽TAT
1 #include<bits/stdc++.h> 2 #define inf 214748364 3 #define N 1002333 4 #define rep(i,l,r) for(int i=l;i<=r;i++) 5 using namespace std; 6 struct Point{ 7 int mx[2],mn[2],d[2],l,r; 8 Point(int x=0,int y=0){ 9 l=0,r=0; d[0]=x,d[1]=y; 10 } 11 }p[N],tr[N],T; 12 int ans,flag,root,m,n; 13 bool operator < (Point a,Point b) { 14 return a.d[flag]<b.d[flag]; 15 } 16 int dis(Point a,Point b){ 17 return abs(a.d[0]-b.d[0])+abs(a.d[1]-b.d[1]); 18 } 19 inline void update(int mid){ 20 int l=tr[mid].l,r=tr[mid].r; 21 rep(i,0,1) { 22 if(tr[mid].l) tr[mid].mn[i]=min(tr[mid].mn[i],tr[l].mn[i]),tr[mid].mx[i]=max(tr[mid].mx[i],tr[l].mx[i]); 23 if(tr[mid].r) tr[mid].mn[i]=min(tr[mid].mn[i],tr[r].mn[i]),tr[mid].mx[i]=max(tr[mid].mx[i],tr[r].mx[i]); 24 } 25 } 26 int build(int l,int r,int now) { 27 flag=now; 28 int mid=(l+r)>>1; 29 nth_element(p+l,p+mid,p+r+1); 30 tr[mid]=p[mid]; 31 rep(i,0,1) tr[mid].mx[i]=tr[mid].mn[i]=tr[mid].d[i]; 32 if(l<mid) tr[mid].l=build(l,mid-1,now^1); 33 if(r>mid) tr[mid].r=build(mid+1,r,now^1); 34 update(mid); 35 return mid; 36 } 37 inline void ins(int k,int now) { 38 if(T.d[now]>=tr[k].d[now]) { 39 if(tr[k].r) ins(tr[k].r,now^1); else { 40 tr[k].r=++n; tr[n]=T; 41 rep(i,0,1) tr[n].mx[i]=tr[n].mn[i]=tr[n].d[i]; 42 } 43 } else { 44 if(tr[k].l) ins(tr[k].l,now^1); else { 45 tr[k].l=++n; tr[n]=T; 46 rep(i,0,1) tr[n].mx[i]=tr[n].mn[i]=tr[n].d[i]; 47 } 48 } 49 update(k); 50 } 51 inline int getdis(int k,Point p) { 52 int ret=0; 53 rep(i,0,1) ret+=max(tr[k].mn[i]-p.d[i],0); 54 rep(i,0,1) ret+=max(p.d[i]-tr[k].mx[i],0); 55 return ret; 56 } 57 void ask(int k,int now) { 58 int d,dl=inf,dr=inf; 59 d=dis(tr[k],T); ans=min(ans,d); 60 if(tr[k].l) dl=getdis(tr[k].l,T); 61 if(tr[k].r) dr=getdis(tr[k].r,T); 62 if(dl<dr) { 63 if(dl<ans) ask(tr[k].l,now^1); 64 if(dr<ans) ask(tr[k].r,now^1); 65 } else { 66 if(dr<ans) ask(tr[k].r,now^1); 67 if(dl<ans) ask(tr[k].l,now^1); 68 } 69 } 70 inline int read(){ 71 int x=0,f=1;char ch=getchar(); 72 while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} 73 while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} 74 return x*f; 75 } 76 inline void insert(Point p) { 77 T=p; ins(root,0); 78 } 79 inline int que(Point p){ 80 ans=inf; T=p; ask(root,0); 81 return ans; 82 } 83 int main () { 84 register int Q,opt,x,y; 85 scanf("%d%d",&n,&Q); 86 rep(i,1,n) scanf("%d%d",&p[i].d[0],&p[i].d[1]); 87 root=build(1,n,0); 88 while(Q--) { 89 opt=read(); x=read(); y=read(); 90 if(opt==1) insert(Point(x,y));else printf("%d\\n",que(Point(x,y))); 91 } 92 }
1941:为什么有的省会拿这种奇奇怪怪的东西来考啊喂...
1 #include<bits/stdc++.h> 2 #define inf 214748364 3 #define N 1002333 4 #define rep(i,l,r) for(int i=l;i<=r;i++) 5 using namespace std; 6 struct Point{ 7 int mx[2],mn[2],d[2],l,r; 8 Point(int x=0,int y=0){ 9 l=0,r=0; d[0]=x,d[1]=y; 10 } 11 }p[N],tr[N],T; 12 int ans,flag,root,m,n,anss; 13 bool operator < (Point a,Point b) { 14 return a.d[flag]<b.d[flag]; 15 } 16 int dis(Point a,Point b){ 17 return abs(a.d[0]-b.d[0])+abs(a.d[1]-b.d[1]); 18 } 19 inline void update(int mid){ 20 int l=tr[mid].l,r=tr[mid].r; 21 rep(i,0,1) { 22 if(tr[mid].l) tr[mid].mn[i]=min(tr[mid].mn[i],tr[l].mn[i]),tr[mid].mx[i]=max(tr[mid].mx[i],tr[l].mx[i]); 23 if(tr[mid].r) tr[mid].mn[i]=min(tr[mid].mn[i],tr[r].mn[i]),tr[mid].mx[i]=max(tr[mid].mx[i],tr[r].mx[i]); 24 } 25 } 26 int build(int l,int r,int now) { 27 flag=now; 28 int mid=(l+r)>>1; 29 nth_element(p+l,p+mid,p+r+1); 30 tr[mid]=p[mid]; 31 rep(i,0,1) tr[mid].mx[i]=tr[mid].mn[i]=tr[mid].d[i]; 32 if(l<mid) tr[mid].l=build(l,mid-1,now^1); 33 if(r>mid) tr[mid].r=build(mid+1,r,now^1); 34 update(mid); 35 return mid; 36 } 37 inline int getdis(int k,Point p) { 38 int ret=0; 39 rep(i,0,1) ret+=max(tr[k].mn[i]-p.d[i],0); 40 rep(i,0,1) ret+=max(p.d[i]-tr[k].mx[i],0); 41 return ret; 42 } 43 void ask(int k,int now) { 44 int d,dl=inf,dr=inf; 45 d=dis(tr[k],T); if(d) ans=min(ans,d); 46 if(tr[k].l) dl=getdis(tr[k].l,T); 47 if(tr[k].r) dr=getdis(tr[k].r,T); 48 if(dl<dr) { 49 if(dl<ans) ask(tr[k].l,now^1); 50 if(dr<ans) ask(tr[k].r,now^1); 51 } else { 52 if(dr<ans) ask(tr[k].r,now^1); 53 if(dl<ans) ask(tr[k].l,now^1); 54 } 55 } 56 inline int que(Point p){ 57 ans=inf; T=p; ask(root,0); 58 return ans; 59 } 60 inline int getmax(int k,Point p) { 61 int ret=0; 62 rep(i,0,1) ret+=max(abs(tr[k].mn[i]-p.d[i]),abs(tr[k].mx[i]-p.d[i])); 63 return ret; 64 } 65 void ask1(int k,int now) { 66 int d,dl=-inf,dr=-inf; 67 d=dis(tr[k],T); ans=max(ans,d); 68 if(tr[k].l) dl=getmax(tr[k].l,T); 69 if(tr[k].r) dr=getmax(tr[k].r,T); 70 if(dl>dr) { 71 if(dl>ans) ask1(tr[k].l,now^1); 72 if(dr>ans) ask1(tr[k].r,now^1); 73 } else { 74 if(dr>ans) ask1(tr[k].r,now^1); 75 if(dl>ans) ask1(tr[k].l,now^1); 76 } 77 } 78 inline int que1(Point p){ 79 ans=-inf; T=p; ask1(root,0); 80 return ans; 81 } 82 int main () { 83 scanf("%d",&n); 84 rep(i,1,n) scanf("%d%d",&p[i].d[0],&p[i].d[1]); 85 root=build(1,n,0); 86 int x,y,a,b; 87 anss=inf; 88 rep(i,1,n) { 89 x=p[i].d[0]; y=p[i].d[1]; 90 a=que(Point(x,y)); b=que1(Point(x,y)); 91 anss=min(anss,b-a); 92 } 93 printf("%d\\n",anss); 94 }
以上是关于KDT的坑...的主要内容,如果未能解决你的问题,请参考以下文章